CSS/Javascript Word Clock
CSS/Javascript Word ClockA little experiment I built: a word clock using CSS3 transforms and a little Javascript to run the actual clock. Useful? Maybe not. Fun? Definitely.
The code behind it is fairly straight-forward. Let's take a peak:
CSS
The first thing we need to do is set a base set of styles for each arm of the clock.
li {
position: absolute;
width: 150px;
text-transform: lowercase;
-webkit-transform-origin: 0 center;
-moz-transform-origin: 0 center;
color: rgba(255, 255, 255, 0.1);
position: absolute;
left: 0;
top: 0;
}
This is basically saying for each arm, position it at the top of the clock body, and then rotate around left side, so that we have uniform rotations.
Then, for each arm, we set the actual rotation. Here is the HTML for the "hour" arms:
<ol id="hours">
<li><span>One</span></li>
<li><span>Two</span></li>
<li><span>Three</span></li>
<li><span>Four</span></li>
<li><span>Five</span></li>
<li><span>Six</span></li>
<li><span>Seven</span></li>
<li><span>Eight</span></li>
<li><span>Nine</span></li>
<li><span>Ten</span></li>
<li><span>Eleven</span></li>
<li><span>Twelve</span></li>
</ol>
And, the corresponding CSS:
#hours > li {
padding: 0 0 0 80px;
}
#hours > li:nth-child(1) {
-webkit-transform: rotate(-60deg);
-moz-transform: rotate(-60deg);
}
#hours > li:nth-child(2) {
-webkit-transform: rotate(-30deg);
-moz-transform: rotate(-30deg);
}
#hours > li:nth-child(3) {
-webkit-transform: rotate(0deg);
-moz-transform: rotate(0deg);
}
#hours > li:nth-child(4) {
-webkit-transform: rotate(30deg);
-moz-transform: rotate(30deg);
}
#hours > li:nth-child(5) {
-webkit-transform: rotate(60deg);
-moz-transform: rotate(60deg);
}
#hours > li:nth-child(6) {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
}
#hours > li:nth-child(7) {
-webkit-transform: rotate(120deg);
-moz-transform: rotate(120deg);
}
#hours > li:nth-child(8) {
-webkit-transform: rotate(150deg);
-moz-transform: rotate(150deg);
}
#hours > li:nth-child(9) {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
}
#hours > li:nth-child(10) {
-webkit-transform: rotate(210deg);
-moz-transform: rotate(210deg);
}
#hours > li:nth-child(11) {
-webkit-transform: rotate(240deg);
-moz-transform: rotate(240deg);
}
#hours > li:nth-child(12) {
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
}
The first line sets the padding, so that each hour arm begins 80px from the center. The rest set up the individual rotations for each arm, at 30 degrees each. The minute and second hands have more padding, and rotate 6 degrees for each arm. The rest of the CSS in the file is used to style the clock, and to show/hide the extra text.
Javascript
All we need to do for the javascript is create a function that sets class="active" on each arm of the current time. So, at 12:45 and 20 seconds, the 12 hour arm, the 45 minute arm, and the 20 second arm have class="active", and the rest are normal. Then we simply set an interval to run every second.
$(function () {
var hours = $('#hours'),
minutes = $('#minutes'),
seconds = $('#seconds');
//these are default grabs so that the first time it runs, it doesn't throw an error
//after that, we use them to cache the current active arm for each group, so that we
//don't have to waste time searching
var cHour = $('html'),
cMinute = $('html'),
cSecond = $('html');
var setCurrentTime = function () {
//establish what the time is
var currentTime = new Date();
var hour = currentTime.getHours() - 1;
if (hour == -1) {
hour = 11;
}
var minute = currentTime.getMinutes() - 1;
if (minute == -1) {
minute = 59;
}
var second = currentTime.getSeconds() - 1;
if (second == -1) {
second = 59;
}
var ampm = 'am';
if (hour > 11) {
ampm = 'pm';
hour = hour - 12;
}
if (hour == 11) {
ampm = 'pm';
}
//remove the active class, and add it to the new time
cHour.removeClass('active');
cHour = hours.children(':eq(' + hour + ')').addClass('active');
cMinute.removeClass('active');
cMinute = minutes.children(':eq(' + minute + ')').addClass('active');
cSecond.removeClass('active');
cSecond = seconds.children(':eq(' + second + ')').addClass('active');
$('body').removeClass('am').removeClass('pm').addClass(ampm);
};
//set the interval to run each second
setInterval(setCurrentTime, 1000);
});
It's a fun little experiment that doesn't have any real value on it's own, but it's a good exercise and as good of an excuse as any to play around with CSS transforms.
The full CSS file can be found here, and the javascript can be found here
Comments (archived for posterity)
- Nate Klaiber commented
That’s just freaking awesome. ha.
- overcriticalpedant commented
Very nice demo I must say
However, can I humbly suggest (as politely as humanly possible) that you make sure your code is cross-browser compatible before accusing browsers you don’t bother supporting that they’re apparently “not up to snuff”.
Obviously I’m not saying you should have to do overly extensive browser testing for what is simply a proof-of-concept test, but just seeing the “not up to snuff” message is just a tiny tiny bit irksome for anyone visiting your page in the most “up to snuff browser” available (in terms of Transform support)
A few things:
1) There are not many CSS vendor prefixes - if you choose to use experimental prefixed properties, putting in a property for each prefix doesn’t take long
2) Modernizr 1.1 doesn’t provide reliable detection for experimental (prefixed) CSS - you could try getting 1.2 on github - it’s slightly better
3) unprefixed properties should always be defined last so as not to have them overridden by experimental ones - i.e. put border-radius AFTER -moz-border-radius as when Firefox eventually implements the standard one it will behave more correctly than the experimental one (which will keep old behaviour for compatibility)Again, apologies for being critical - it’s intent is purely constructive as this is a REALLY SWEET demo that I’d love to see working properly for everyone
- Dan Ott commented
@oc Pendant - Thanks for the thoughts. Constructive criticisms are good!
The “up to snuff” thing was a last-second addition meant to avoid confusion, and not too well thought out, obviously. I’ll tweak the language and settings. Also, Thanks for letting me know about the Modernizr updated, I’ll check that out pronto.
I definitely did not include all of the available vendor prefixes, either. I’ll take a look.
Can I ask what browser you were using, just so I can make sure things are working correctly once I tweak things? I made an assumption that Modernizer would tell me when I could rely on css transform support, but I’ve seen it be wrong before.
Anyway, thanks.
- Bruno commented
This code with a few adjustments would make an absolutelly great countdown clock that would fit very well on teasers and hot sites. Just random thought…
- Eric Wiley commented
I think that may be the most attention I’ve every paid to a clock since my Mickey Mouse watch. Thanks for sharing, I really enjoyed it.
- Josh Walsh commented
This is really cool. I’ve actually been playing with a concept that’s similar, except that the current values stay fixed in place and the clock rotates around the value. Like a clock where the hands stay still and everything else moves around it.
Thanks for sharing this.
- overcriticalpedant commented
@Dan Ott
Thanks for the response.FYI:
Vendor-prefixes are listed here: http://www.w3.org/TR/CSS2/syndata.html#vendor-keyword-history
Of those, -xv- is for xhtml voice only (I see your site is html so that definitely never applies) and most of the rest are non-browsers or outdated, leaving only -o- and -khtml- missing from your list (and -ms- if you absolutely must… )The major bug in Modernizr was in it’s vendor-prefix support - they check using simple javascript object detection and were checking for el.mozBorderRadius instead of el.MozBorderRadius (mis-capitalisation) - they’ve since fixed this in 1.2pre.
I was using the Opera browser - it has the most complete and stable CSS Transforms support as it was added later than Webkit’s and is therefore a better reflection of the current draft of the w3c spec. It’s still not necessarily 100% though as the spec’s not finished.
- patt commented
Thought this was feckin cool… any chance getting it as an app for iPhone… I’d give yah 49p…
- Grenadier commented
this is very cool !!!
- Pascal commented
hello,
really nice work, it reminds me this one which is not a JS but a designer clock you can buy for 1000$ (sic).
http://walyou.com/wall-clock-no-numbers-design/
maybe you could inspire yourself from it for the next gen?best regards,
Pascal - Rabii commented
This is totally amazing man. You can add a feature that can change to white background in day time and black in night time.