Let’s construct a totally functioning and settable “analog” clock with CSS customized properties and the calc() perform. Then we’ll convert it right into a “digital” clock as properly. All this with no JavaScript!
Right here’s a fast have a look at the clocks we’ll make:
Brushing up on the calc() perform
CSS preprocessors teased us endlessly with the flexibility to calculate numerical CSS values. The issue with pre-processors is that they lack information of the context after the CSS code has compiled. This is the reason it’s unattainable to say you need your ingredient width to be 100% of the container minus 50 pixels. This produces an error in a preprocessor:
width: 100% – 50px;
// error: Incompatible models: ‘px’ and ‘%’
Preprocessors, as their identify suggests, preprocess your directions, however their output remains to be simply plain outdated CSS which is why they’ll’t reconcile totally different models in your arithmetic operations. Ana has gone into nice element on the conflicts between Sass and CSS options.
The excellent news is that native CSS calculations should not solely doable, however we will even mix totally different models, like pixels and percentages with the calc() perform:
width: calc(100% – 50px);
calc() can be utilized anyplace a size, frequency, angle, time, proportion, quantity, or integer is allowed. Try the CSS Information to CSS Features for a whole overview.
What makes this much more highly effective is the truth that you’ll be able to mix calc() with CSS customized properties—one thing preprocessors are unable to deal with.
The arms of the clock
Let’s lay out the foundations first with a couple of customized properties and the animation definition for the arms of the analog clock:
:root {
–second: 1s;
–minute: calc(var(–second) * 60);
–hour: calc(var(–minute) * 60);
}
@keyframes rotate {
from { rework: rotate(0); }
to { rework: rotate(1turn); }
}
Every thing begins within the root context with the –second customized property the place we outlined {that a} second ought to be, properly, one second (1s). All future values and timings shall be derived from this.
This property is basically the guts of our clock and controls how briskly or sluggish the entire clock’s arms go. Setting –second to 1s makes the clock match real-life time however we might make it go at half pace by setting it to 2s, and even 100 instances sooner by setting it to 10ms.
The primary property we’re calculating is the –minute hand, which we would like equal to 60 instances one second. We will reference the worth from the –second property and multiply it by 60 with the assistance of calc() :
–minute: calc(var(–second) * 60);
The –hour hand property is outlined utilizing the very same precept however multiplied by the –minute hand worth:
–hour: calc(var(–minute) * 60);
We would like all three arms on the clock to rotate from 0 to 360 levels—across the form of the clock face! The distinction between the three animations is how lengthy it takes every to go all the way in which round. As an alternative of utilizing 360deg as our full-circle worth, we will use the superbly legitimate CSS worth of 1turn.
@keyframes rotate {
from { rework: rotate(0); }
to { rework: rotate(1turn); }
}
These @keyframes merely inform the browser to show the ingredient round as soon as through the animation. We now have outlined an animation named rotate and it’s now able to be assigned to the clock’s second hand:
.second.hand {
animation: rotate steps(60) var(–minute) infinite;
}
We’re utilizing the animation shorthand property to outline the small print of the animation. We added the identify of the animation (rotate), how lengthy we would like the animation to run (var(–minute), or 60 seconds) and what number of instances to run it (infinite, which means it by no means stops operating). steps(60) is the animation timing perform which tells the browser to carry out the 1-turn animation in 60 equal steps. This fashion, the seconds hand ticks at every second moderately than rotating easily alongside the circle.
Whereas we’re discussing CSS animations, we will outline an animation delay (animation-delay) if we would like the animation to begin later, and we will change whether or not the animation ought to play forwards or backwards utilizing animation-direction. We will even pause and restart the animations with animation-play-state.
The animation on the minute and hour arms will work very very similar to on the second hand. The distinction is that a number of steps are pointless right here—these arms can rotate in a easy, linear vogue.
The minute hand takes one hour to finish one full flip, so:
.minute.hand {
animation: rotate linear var(–hour) infinite;
}
On the opposite hand (pun meant) the hour hand takes twelve hours to go across the clock. We don’t have a separate customized property for this period of time, like –half-day, so we’ll multiply –hour by twelve:
.hour.hand {
animation: rotate linear calc(var(–hour) * 12) infinite;
}
You in all probability get the concept of how the arms of the clock work by now. However it could not be an entire instance if we didn’t truly construct the clock.
The clock face
Thus far, we’ve solely regarded on the CSS facet of the clock. We additionally want some HTML for all that to work. Right here’s what I’m utilizing:
<predominant>
<div class=”clock”>
<div class=”second hand”></div>
<div class=”minute hand”></div>
<div class=”hour hand”></div>
</div>
</predominant>
Let’s see what now we have to do to type our clock:
.clock {
width: 300px;
top: 300px;
border-radius: 50%;
background-color: var(–grey);
margin: 0 auto;
place: relative;
}
We made the clock 300px tall and huge, made the background shade gray (utilizing a customized property, –grey, we will outline later) and turned it right into a circle with a 50% border radius.
There are three arms on the clock. Let’s first transfer these to the middle of the clock face with absolute positioning:
.hand {
place: absolute;
left: 50%;
high: 50%;
}
Discover the identify of this class (.arms) as a result of all three arms use it for his or her base types. That’s necessary as a result of any adjustments to this class are utilized to all three arms.
Let’s outline the hand dimensions and shade issues up:
.hand {
place: absolute;
left: 50%;
high: 50%;
width: 10px;
top: 150px;
background-color: var(–blue);
}
The arms are actually all in place:
Getting correct rotation
Let’s maintain off celebrating only a second. We now have a couple of points and they may not be apparent when the clock arms are this skinny. What if we alter them to be 100px huge:
We will now see that if a component is positioned 50% from the left, it’s aligned to the middle of the dad or mum ingredient—however that’s not precisely what we want. To repair this, the left coordinate must be 50%, minus half the width of the hand, which is 50px in our case:
Working with a number of totally different measurements is a breeze for the calc() perform:
.hand {
place: absolute;
left: calc(50% – 50px);
high: 50%;
width: 100px;
top: 150px;
background-color: var(–grey);
}
This fixes our preliminary positioning, nonetheless, if we attempt to rotate the ingredient we will see that the rework origin, which is the pivot level of the rotation, is on the heart of the ingredient:
We will use the transform-origin property to alter the rotation origin level to be on the heart of the x-axis and on the high on the y-axis:
.hand {
place: absolute;
left: calc(50% – 50px);
high: 50%;
width: 100px;
top: 150px;
background-color: var(–grey);
transform-origin: heart 0;
}
That is nice, however not excellent as a result of our pixel values for the clock arms are hardcoded. What if we would like our arms to have totally different widths and heights, and scale with the precise dimension of the clock? Sure, you guessed proper: we want a couple of CSS customized properties!
.second {
–width: 5px;
–height: 140px;
–color: var(–yellow);
}
.minute {
–width: 10px;
–height: 90px;
–color: var(–blue);
}
.hour {
–width: 10px;
–height: 50px;
–color: var(–dark-blue);
}
With this, we’ve outlined customized properties for the person arms. What’s attention-grabbing right here is that we gave these properties the identical names: –width, –height, and –color. How is it doable that we gave them totally different values however they don’t overwrite one another? And which worth will I get again if I name var(–width), var(–height) or var(–color)?
Let’s have a look at the hour hand:
<div class=”hour hand”></div>
We assigned new customized properties to the .hour class and they’re regionally scoped to the ingredient, which incorporates the ingredient and all its kids. This implies any CSS type utilized to the ingredient—or its kids accessing the customized properties—will see and use the precise values that have been set inside their very own scope. So in the event you name var(–width) contained in the hour hand ingredient or any ancestor components inside that, the worth returned from our instance above is 10px. This additionally implies that if we strive utilizing any of those properties exterior these components—for instance contained in the physique ingredient—they’re inaccessible to these components exterior the scope.
Transferring on to the arms for seconds and minutes, we enter a special scope. Which means the customized properties may be redefined with totally different values.
.second {
–width: 5px;
–height: 140px;
–color: var(–yellow);
}
.minute {
–width: 10px;
–height: 90px;
–color: var(–blue);
}
.hour {
–width: 10px;
–height: 50px;
–color: var(–dark-blue);
}
.hand {
place: absolute;
high: 50%;
left: calc(50% – var(–width) / 2);
width: var(–width);
top: var(–height);
background-color: var(–color);
transform-origin: heart 0;
}
The beauty of that is that the .hand class (which we assigned to all three hand components) can reference these properties for the calculations and declarations. And every hand will obtain its personal properties from its personal scope. In a method, we’re personalizing the .hand class for every ingredient to keep away from pointless repetition in our code.
Our clock is up and operating and all arms are shifting on the appropriate pace:
We might cease right here however let me counsel a couple of enhancements. The arms on the clock begin at 6 o’clock, however we might set their preliminary positions to 12 o’clock by rotating the clock 180 levels. Let’s add this line to the .clock class:
.clock {
/* similar as earlier than */
rework: rotate(180deg);
}
The arms would possibly look good with rounded edges:
.hand {
/* similar as earlier than */
border-radius: calc(var(–width) / 2);
}
Our clock appears to be like and works nice! And all arms begin from 12 o’clock, precisely how we would like it!
Setting the clock
Even with all these superior options, the clock is unusable as it fails terribly at telling the precise time. Nonetheless, there are some exhausting limitations to what we will do about this. It’s merely not doable to entry the native time with HTML and CSS to routinely set our clock. However we will put together it for handbook setup.
We will set the clock to begin at a sure hour and minute and if we run the HTML at precisely that point it should preserve the time precisely afterwards. That is mainly the way you set a real-world clock, so I believe that is a suitable answer. 😅
Let’s add the time we wish to begin the clock as customized properties contained in the .clock class:
.clock {
–setTimeHour: 16;
–setTimeMinute: 20;
/* similar as earlier than */
}
The present time for me as I write is coming as much as 16:20 (or 4:20) so the clock shall be set to that point. All I must do is refresh the web page at 16:20 and it’ll preserve the time precisely.
OK, however… how can we set the time to those positions and rotate the arms if a CSS animation is already controlling the rotation?
Ideally, we wish to rotate and set the arms of the clock to a selected place when the animation begins on the very starting. Say you wish to set the hour hand to 90 levels so it begins at 3:00 pm and initialize the rotation animation from this place:
/* this is not going to work */
.hour.hand {
rework: rotate(90deg);
animation: rotate linear var(–hour) infinite;
}
Effectively, sadly, this is not going to work as a result of the rework is instantly overridden by the animation, because it modifies the exact same rework property. So, it doesn’t matter what we set this to, it should return to 0 levels the place the primary keyframe of the animation begins.
We will set the rotation of the hand independently from the animation. For instance, we might wrap the hand into an additional ingredient. This further dad or mum ingredient, the “setter,” can be answerable for setting the preliminary place, then the hand ingredient inside might animate from 0 to 360 levels independently. The beginning 0-degree place would then be relative to what we set the dad or mum setter ingredient to.
This could work however fortunately there’s a greater possibility! Let me amaze you! 🪄✨✨
The animation-delay property is what we often use to begin the animation with some predefined delay.
The trick is to use a damaging worth, which begins the animation instantly, however from a selected level within the animation timeline!
To begin 10 seconds into the animation:
animation-delay: -10s;
In case of the hour and minute arms, the precise worth we want for the delay is calculated from the –setTimeHour and –setTimeMinute properties. To assist with the calculation, let’s create two new properties with the period of time shifting we want:
The hour hand must be the hour we wish to set the clock, multiplied by an hour.The minute hand shifts the minute we wish to set the clock multiplied by a minute.
–setTimeHour: 16;
–setTimeMinute: 20;
–timeShiftHour: calc(var(–setTimeHour) * var(–hour));
–timeShiftMinute: calc(var(–setTimeMinute) * var(–minute));
These new properties include the precise period of time we want for the animation-delay property to set our clock. Let’s add these to our animation definitions:
.second.hand {
animation: rotate steps(60) var(–minute) infinite;
}
.minute.hand {
animation: rotate linear var(–hour) infinite;
animation-delay: calc(var(–timeShiftMinute) * -1);
}
.hour.hand {
animation: rotate linear calc(var(–hour) * 12) infinite;
animation-delay: calc(var(–timeShiftHour) * -1);
}
Discover how we multiplied these values by -1 to transform them to a damaging quantity.
We now have virtually reached perfection with this, however there’s a slight challenge: if we set the variety of minutes to 30, for instance, the hour hand must already be midway by way of to the following hour. An excellent worse scenario can be to set the minutes to 59 and the hour hand remains to be at first of the hour.
repair this, all we have to do is add the minute shift and the hour shift values collectively for the hour hand:
.hour.hand {
animation: rotate linear calc(var(–hour) * 12) infinite;
animation-delay: calc(
(var(–timeShiftHour) + var(–timeShiftMinute)) * -1
);
}
And I believe with this now we have fastened the whole lot. Let’s admire our lovely, pure CSS, settable, analog clock:
Let’s go digital
In precept, an analog and a digital clock each use the identical calculations, the distinction being the visible illustration of the calculations.
Right here’s my thought: we will create a digital clock by organising tall, vertical columns of numbers and animate these as an alternative of rotating the clock arms. Eradicating the overflow masks from the ultimate model of the clock container reveals the trick:
The brand new HTML markup must include all of the numbers for all three sections of the clock from 00 to 59 on the second and minute sections and 00 to 23 on the hour part:
<predominant>
<div class=”clock”>
<div class=”hour part”>
<ul>
<li>00</li>
<li>01</li>
<!– and so on. –>
<li>22</li>
<li>23</li>
</ul>
</div>
<div class=”minute part”>
<ul>
<li>00</li>
<li>01</li>
<!– and so on. –>
<li>58</li>
<li>59</li>
</ul>
</div>
<div class=”second part”>
<ul>
<li>00</li>
<li>01</li>
<!– and so on. –>
<li>58</li>
<li>59</li>
</ul>
</div>
</div>
</predominant>
To make these numbers line up, we have to write some CSS, however to get began with the styling we will copy over the customized properties from the :root scope of the analog clock immediately, as time is common:
:root {
–second: 1s;
–minute: calc(var(–second) * 60);
–hour: calc(var(–minute) * 60);
}
The outermost wrapper ingredient, the .clock, nonetheless has the exact same customized properties for setting the preliminary time. All that’s modified is that it turns into a flexbox container:
.clock {
–setTimeHour: 14;
–setTimeMinute: 01;
–timeShiftHour: calc(var(–setTimeHour) * var(–hour));
–timeShiftMinute: calc(var(–setTimeMinute) * var(–minute));
width: 150px;
top: 50px;
background-color: var(–grey);
margin: 0 auto;
place: relative;
show: flex;
}
The three unordered lists and the checklist gadgets inside them that maintain the numbers don’t want any particular therapy. The numbers will stack on high of one another if their horizontal house is restricted. Let’s simply guarantee that there isn’t any checklist styling to forestall bullet factors and that we heart issues for constant placement:
.part > ul {
list-style: none;
margin: 0;
padding: 0;
}
.part > ul > li {
width: 50px;
top: 50px;
font-size: 32px;
text-align: heart;
padding-top: 2px;
}
The format is finished!
Outdoors every unordered checklist is a <div> with a .part class. That is the ingredient that wraps every part, so we will use it as a masks to cover the numbers that fall exterior the seen space of the clock:
.part {
place: relative;
width: calc(100% / 3);
overflow: hidden;
}
The construction of the clock is finished and the rails are actually able to be animated.
Animating the digital clock
The fundamental thought behind the entire animation is that the three strips of numbers may be moved up and down inside their masks to indicate totally different numbers from 0 to 59 for seconds and minutes, and 0 to 23 for hours (for a 24-hour format).
We will do that by altering the translateY transition perform in CSS for the person strips of numbers from 0 to -100%. It’s because 100% on the y-axis represents the peak of the entire strip. A worth of 0% will present the primary quantity, and 100% will present the final quantity of the present strip.
Beforehand, our animation was primarily based on rotating a hand from 0 to 360 levels. We now have a special animation that strikes the quantity strips from 0 to -100% on the y-axis:
@keyframes tick {
from { rework: translateY(0); }
to { rework: translateY(-100%); }
}
Making use of this animation to the seconds quantity strip may be accomplished the identical method because the analog clock. The one distinction is the selector and the identify of the animation that’s referenced:
.second > ul {
animation: tick steps(60) var(–minute) infinite;
}
With the step(60) setting, the animation ticks between numbers like we did for the second hand on the analog clock. We might change this to ease after which the numbers would easily slide up and down as in the event that they have been on a ribbon of paper.
Assigning the brand new tick animation to the minute and hour sections is simply as easy:
.minute > ul {
animation: tick steps(60) var(–hour) infinite;
animation-delay: calc(var(–timeShiftMinute) * -1);
}
.hour > ul {
animation: tick steps(24) calc(24 * var(–hour)) infinite;
animation-delay: calc(var(–timeShiftHour) * -1);
}
Once more, the declarations are very comparable, what’s totally different this time is the selector, the timing perform, and the animation identify.
The clock now ticks and retains the proper time:
Yet one more element: The blinking colon (:)
Once more we might cease right here and name it a day. However there’s one final thing we will do to make our digital clock just a little extra reasonable: make the colon separator between the minutes and seconds blink as every second passes.
We might add these colons within the HTML however they don’t seem to be a part of the content material. We would like them to be an enhancement to the looks and elegance of the clock, so CSS is the proper place to retailer this content material. That’s what the content material property is for and we will apply it to the ::after pseudo-elements for the minutes and hours:
.minute::after,
.hour::after {
content material: “:”;
margin-left: 2px;
place: absolute;
high: 6px;
left: 44px;
font-size: 24px;
}
That was straightforward! However how can we make the seconds colon blink too? We would like it animated so we have to outline a brand new animation? There are lots of methods to realize this however I believed we should always change the content material property this time to show that, fairly unexpectedly, it’s doable to alter its worth throughout an animation:
@keyframes blink {
from { content material: “:”; }
to { content material: “”; }
}
Animating the content material property will not be going to work in each browser, so you could possibly simply change that to opacity or visibility as a secure possibility…
The ultimate step is to assign the blink animation to the pseudo-element of the minute part:
.minute::after {
animation: blink var(–second) infinite;
}
And with that, we’re all accomplished! The digital clock retains the time precisely and we even managed so as to add a blinking separator between the numbers.
E book: All you want is HTML and CSS
This is only one instance undertaking from my new e book, All you want is HTML and CSS. It’s obtainable on Amazon in each the U.S and U.Ok.
In case you are simply getting began with net growth, the concepts within the e book will assist you stage up and construct interactive, animated net interfaces with out touching any JavaScript.
In case you are a seasoned JavaScript developer, the e book is an efficient reminder that many issues may be constructed with HTML and CSS alone, particularly now that now we have much more highly effective CSS instruments and options, like those we coated on this article. There are lots of examples within the e book pushing the bounds together with interactive carousels, accordions, calculating, counting, superior enter validation, state administration, dismissible modal home windows, and reacting to mouse and keyboard inputs. There’s even a totally working star ranking widget and a procuring basket.
Thanks for spending the time to construct clocks with me!
The put up Of Course We Can Make a CSS-Solely Clock That Tells the Present Time! appeared first on CSS-Methods. You possibly can assist CSS-Methods by being an MVP Supporter.
Subscribe to MarketingSolution.
Receive web development discounts & web design tutorials.
Now! Lets GROW Together!