CSS: Creating a clock with border-radius - html

I decided to try and create an analog 12 hour clock with some basic CSS properties. I start off by creating a square div of 500px. I then set the border-radius to 250px and get a nice looking circle. After this, I add in the twelve tick marks, position them absolute-ly, and get their corresponding positions.
The angle for each tick mark is based on this (apologies for spelling out the simple math):
12 tick marks
360° in our circle
360 / 12 = 30° angles
The position for each tick mark can be calculated using some basic trigonometry. I know θ (0°, 30°, 60°, etc.) and radius (250), and by using cos and sin, I can figure out the associated top, bottom, left, and right values. To get the left or right value (x), I can simply use: r * sin θ. To get the top or bottom value (y), I can use: r - (r * cos θ). Hopefully the image below (excuse the MS Paint lack of skill) can help clear up what I'm trying to do.
Once I have these equations, it becomes much easier to get the respective x and y values:
θ (angle) | 250 * sin θ [x] | 250 - (250 * cos θ) [y]
--------------------------------------------------------------
30° (1:00) | right: 125px | top: 33.5px
60° (2:00) | right: 33.5px | top: 125px
90° (3:00) | right: 0px | top: 250px
120° (4:00) | right: 33.5px | bottom: 125px
150° (5:00) | right: 125px | bottom: 33.5px
180° (6:00) | right: 250px | bottom: 0px
210° (7:00) | left: 125px | bottom: 33.5px
240° (8:00) | left: 33.5px | bottom: 125px
270° (9:00) | left: 0px | bottom: 250px
300° (10:00) | left: 33.5px | top: 125px
330° (11:00) | left: 125px | top: 33.5px
360° (12:00) | left: 250px | top: 0px
Now that I've dragged the question on for far too long... my question is, why would my tick marks for 2, 3, 4, 8, 9, and 10 all be a bit off? Based on my calculations (I've always wanted to say that), I shouldn't be having these issues. Sure, I did some rounding and left off some sig figs, but they are not that significant to make the positioning look wonky. Here is my code:
The HTML
<body>
<div id="clock">
<div id="one" class="oneEleven tick"></div>
<div id="two" class="twoTen tick"></div>
<div id="three" class="threeNine tick"></div>
<div id="four" class="fourEight tick"></div>
<div id="five" class="fiveSeven tick"></div>
<div id="six" class="sixTwelve tick"></div>
<div id="seven" class="fiveSeven tick"></div>
<div id="eight" class="fourEight tick"></div>
<div id="nine" class="threeNine tick"></div>
<div id="ten" class="twoTen tick"></div>
<div id="eleven" class="oneEleven tick"></div>
<div id="twelve" class="sixTwelve tick"></div>
</div>
</body>
The CSS
#clock {
height: 500px;
width: 500px;
border-radius: 50%;
border: 1px solid black;
position: relative;
}
.tick {
background-color: black;
height: 20px;
width: 5px;
position: absolute;
}
.oneEleven {
/* ~6.7% */
top: 33.5px;
}
.twoTen {
/* 25% */
top: 125px;
}
.threeNine {
/* 50% */
top: 250px;
}
.fourEight {
/* 25% */
bottom: 125px;
}
.fiveSeven {
/* ~6.7% */
bottom: 33.5px;
}
#one {
right: 125px;
transform: rotate(30deg);
}
#two {
/* ~93.3% */
right: 33.5px;
transform: rotate(60deg);
}
#three {
right: 0px;
transform: rotate(90deg);
}
#four {
right: 33.5px;
transform: rotate(120deg);
}
#five {
right: 125px;
transform: rotate(150deg);
}
#six {
left: 250px;
bottom: 0px;
}
#seven {
left: 125px;
transform: rotate(-150deg);
}
#eight {
left: 33.5px;
transform: rotate(-120deg);
}
#nine {
left: 0px;
transform: rotate(-90deg);
}
#ten {
left: 33.5px;
transform: rotate(-60deg);
}
#eleven {
left: 125px;
transform: rotate(-30deg);
}
#twelve {
left: 250px;
top: 0px;
}
The jsFiddle. It's not entirely obvious on first glance, but if you look at the tick marks I've referenced, you'll see they're not lined up on the circle. I'm eventually going to move to percentages, but I would like to know why they're off, and is this the best approach for creating a circle that you'd like to add styling too? I realize there's the HTML5 canvas tag, but I feel like that would be too difficult to work with and would be doing more processing than I need to perform...
Any help would be appreciated!

It looks like you've positioned each tick to get one corner in the right position on the circle. But then the tick gets rotated about the origin, which pushes part of it outside the circle. You should be able to fix it by setting transform-origin appropriately for each tick. You need to rotate about the same corner you've positioned. So if you positioned with top and right, set the transform-origin to "top right". For example:
#two {
/* ~93.3% */
right: 33.5px;
transform: rotate(60deg);
transform-origin: top right;
}

Related

Align rotated text to left of canvas

I am trying to add a rotated Y axis title (SPEED (MPH)) to my chart. It simple doesn't align to where I want which is to the far left as pointed out in the image. Have tried to mess with positions and margins. I either ends up shifting the chart canvas below the label or the chart canvas moves out of the blue box. Also using Bootstrap grid system in this instance. Any advice please. Thanks.
<! -- html -->
<div class="col-sm-4">
<div class="k-livestat_box">
<h3>Speed Status</h3>
<hr>
<div class="radar-chart-sz">
<!--Line Speed Chart -->
<label class="ylabel">Speed ( mph )</label>
<canvas id="lineChart"></canvas>
</div>
<h4 id="currentspeed">Current Speed ( mph ): 100</h4>
<h4 id="topspeed">Highest Speed ( mph ): 100</h4>
<h4 id="lowspeed">Lowest Speed ( mph ): 100</h4>
<h4 id="avgspeed">Average Speed ( mph ): 100</h4>
</div>
</div>
..
/*CSS*/
.ylabel {
float: left;
position: absolute;
margin-top: 60px;
text-align: center;
/* Rotate div */
-ms-transform: rotate(270deg); /* IE 9 */
-webkit-transform: rotate(270deg); /* Chrome, Safari, Opera */
transform: rotate(270deg);
}​
.radar-chart-sz{
padding-left: 0 !important;
margin-top: 20px;
}
.k-livestat_box {
margin: 15px 2.5px;
padding: 25px;
min-height: 458px;
max-width: 100%;
background-color: #1A284B;
color: #C3CF01;
border: 1px solid #162444;
}
Just add in a transform-origin and then a translate for adjusting
...
transform-origin: 0% 50%;
transform: rotate(270deg) translate(-25%, -50%);
}
Fiddle - http://jsfiddle.net/kyt3Lmyc/

Infinity Symbol in CSS

I'm looking at creating a Infinity Symbol using CSS, SVG or Canvas.
If you don't know what an infinity symbol is, this is an example:
I have attempted at created the shape but have only managed to create one side of the shape. I would ultimately like to keep this to one element and as simple as possible.
.infinity {
width: 100px;
height: 100px;
border-radius: 50% 50% 0 50%;
border: 5px solid black;
transform: rotate(-45deg);
}
<div class="infinity"></div>
I have found this question:
Infinity symbol with HTML
But i'm looking at using this as an icon or image of some sort and therefore would like a bit more freedom with the shape.
CSS
By using pseudo-elements, you can create both sides of the shape and therefore get the output required.
This solution will be well supported across all browsers.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 50px 50px 0 50px;
transform: rotate(-45deg);
}
div:after {
left: auto;
right: 0;
border-radius: 50px 50px 50px 0;
transform: rotate(45deg);
}
<div></div>
This is an amended version from here: CSS-Tricks
If you want it more shapely, a bit of amending to the border radius rules really help give it some more shape.
div {
position: relative;
width: 178px;
height: 100px;
}
div:before,
div:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
border: 10px solid black;
border-radius: 80% 0 55% 50% / 55% 0 80% 50%;
transform: rotate(45deg);
}
div:after {
left: auto;
right: 0;
transform: rotate(-135deg);
}
<div></div>
SVG
SVG stands for Scalable Vector Graphic. The web browser views it as an image but you can add text and normal HTML elements within an SVG.
It is well supported across all browsers as viewable here: CanIUse
SVG | MDN
<svg height="150" viewbox="0 50 200 200">
<path fill="none" stroke="#333333" stroke-width="5" d="M100,100
C200,0 200,200 100,100
C0,0 0,200 100,100z" />
</svg>
Canvas
Canvas is similar to SVG but uses a raster (pixel based) instead of a vector to create the shape.
The browser support for Canvas is quite good.
var shape = document.getElementById('infinity').getContext('2d');
shape.lineWidth = 6;
shape.strokeStyle = "#333";
shape.beginPath();
shape.moveTo(100, 100);
shape.bezierCurveTo(200, 0, 200, 200, 100, 100);
shape.bezierCurveTo(0, 0, 0, 200, 100, 100);
shape.closePath();
shape.stroke();
<canvas id="infinity"></canvas>
HTML
As taken from the answer's in the near duplicate, this is an accumulation of all the HTML alternatives.
I've only added this for canonical and to show to users that the shape is possible with HTML entities.
p {
font-size: 2em;
}
<p>∞</p>
<p>∞</p>
<p>∞</p>
<p>∞</p>

CSS sprite with pseudo classes in all corners

I found this codepen which is using this sprite to add the corners:
with this code:
.lol-promo:before,
.lol-promo:after {
background: url("http://s.cdpn.io/800/ornaments-sprite.png") no-repeat;
content: "";
height: 40px;
position: absolute;
top: 0; left: 0;
width: 95px;
}
.lol-promo:after {
background-position: -95px 0;
left: auto; right: 0;
}
but in the codepen example is using only the top corners, how can i add the bottom corners too, to a simple div? i tried some things like repeating div:after part but is not working. I think its simple but i am not getting the point.
Thanks in advance
You can make use of the CSS3 border-image property.
You define how the image will get sliced and the width of the border. The slice rule takes four values each defining top, right, bottom and left corners of the box respectively. This way, you don't need any pseudo-elements.
Give your markup: <section class="lol-promo"></section>..
All you need is this CSS:
.lol-promo {
...
border-image: url('//s.cdpn.io/800/ornaments-sprite.png');
border-image-slice: 40 96 40 96;
border-image-width: auto;
}
The slice is based off the image that you referenced to in your question. For any other image, you need to tweak those values depending on how you want the border to appear.
Example Snippet:
.lol-promo {
height: 120px; width: 320px; margin: 16px; padding: 16px;
background-color: rgba(0,0,128,0.1);
border-image: url('//s.cdpn.io/800/ornaments-sprite.png');
border-image-slice: 40 96 40 96;
border-image-width: auto;
}
<section class="lol-promo">
<h2>header</h2>
<p>Lorem ipsum</p>
</section>
Example Fiddle: http://jsfiddle.net/abhitalks/05Lx7eea/
You can duplicate that div .lol-promo and flip the bottom ones vertically with transform:scale and absolute position them to the bottom right and left of your page. Here's a fiddle https://jsfiddle.net/az6juLkq/1/ with the full code.
.lol-promo.left,
.lol-promo.right {
position: absolute;
-moz-transform: scale(1, -1);
-webkit-transform: scale(1, -1);
-o-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
.lol-promo.left{
bottom: 0; left: 0;
}
.lol-promo.right {
bottom: 0; right: 0;
background-position: -95px 0;
right: 0px;
}
In order to accomplish the flip, you can use a CSS transform. This may be done within the pseudo-element itself if you wish.
-moz-transform: scale(1, -1);
-webkit-transform: scale(1, -1);
-o-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
In the linked example, notice the border is technically border-top, yet it appears on the bottom.
CODEPEN: http://codepen.io/pohuski/pen/bVBpNw

css form input corner box

I am trying to create a div to align with the bottom corner of a form input but with a triangular arrow pointing to the corner and merged into the box. I am having problems creating this as i am not a designer. Basically what i'm looking for is a kind of arrow that merges with the box (maybe like a speech bubble)
Anyway code so far:
html:
<div class="inputwrap">
<select id="gb_contact" name="gb_contact" class="dropdown-input" >
<option value="option">option</option>
</select>
<div class="tip">rrrrrrrrrrr</div>
</div>
css
.inputwrap{
position: relative;
display: inline-block;
min-width: 10%;
}
.tip:before {
position: absolute;
content: " ";
width: 0;
height: 0;
border-style: solid;
border-width: 15px 15px 0 0;
border-color: #00FF00 transparent transparent transparent;
z-index: 100;
left: -0px;
top: -2px;
-ms-transform: rotate(5deg); /* IE 9 */
-webkit-transform: rotate(5deg); /* Chrome, Safari, Opera */
transform: rotate(5deg);
}
.tip {
position: absolute;
right: -190px;
background-color:#ff0000;
min-width:200px;
min-height: 50px;
margin-top:2px;
border-radius:5px;
}
can anyone help with this?
jsfiddle: http://jsfiddle.net/d30top88/
link to concept:
https://drive.google.com/file/d/0B9ZIIks7bG2QT2haMWZZcXM3ZWc/edit?usp=sharing
close enough i suppose :
http://jsfiddle.net/d30top88/4/
What do you mean with merged inside the box? Just adjusted your fiddle like that:
Arrow Demo
with some adjustments:
top: 12px;
-ms-transform: rotate(135deg); /* IE 9 */
-webkit-transform: rotate(135deg); /* Chrome, Safari, Opera */
transform: rotate(135deg);
So it the arrow is now pointed to the right and down in the div.
Update after image link was provided in question:
Arrow Demo 2
But based on the image maybe the arrow has not the appropriate shape to meet your requirements. There are some nice css arrow generators online, just google for "css arrow generator" as I don't want to promote a special one.

CSS3: Calculate difference between (left + scale3d) and (transition3d + scale3d)

Why is there a difference between (scale3d and left) and (scale3d and translate3d)? And how do I calculate the difference between them?
See example: jsBin
div {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background: rgba(0,0,0, .3);
border-radius:7px;
font-size:20px;
-webkit-transform-origin:50% 50%;
}
#t1 {
left: 200px;
-webkit-transform: scale3d(0.5, 0.5, 1);
}
#t2 {
top: 200px;
-webkit-transform: scale3d(0.5, 0.5, 1) translate3d(200px, 0, 0);
}
and the simple HTML:
<div id="t1">scale3d and left</div>
<div id="t2">scale3d and transition3d</div>
CSS3 Transforms alter the local coordinate system. When you scale an element you're also scaling any translations applied to that div. Here - if you change the translate to 400px - you get the same result (reversing the effect of the scale).
You can check what transformations are currently applied to an element by using getComputedStyle().