Having read the blurb around Safari’s CSS transitions I opted to familiarize myself with a quick project — the aim of which was to create a functional, CSS only, analogue clock.
Result
Experiment: CSS Analogue Clock
Experiment works in Safari 4 Beta and Google Chrome. A working clock that optionally resorts to JavaScript to grab the current time (can be achieved by other means).
How To
Before getting into the nitty gritty I created four images, a clock face and three transparent PNG hands (seconds, minutes and hours), ensuring that each of these were the same size so that when overlayed their centres would align. The HTML and CSS to get us going is as follows:
<div id="clock"> <div id="hour"><img src="images/hourHand.png" /></div> <div id="minute"><img src="images/minuteHand.png" /></div> <div id="second"><img src="images/secondHand.png" /></div> </div>
#clock {
position: relative;
width: 378px;
height: 378px;
background-image: url('../images/clockFace.png');
left: 50%;
margin: 5em 0 0 -189px;
}
#clock div {
position: absolute;
}
The magic that rotates the clock’s hands comes via two WebKit specific CSS properties, -webkit-transition (documentation) and -webkit-transform (documentation). The transform property can alter the appearance of an element via a two dimensional transformation, for instance: scaling, rotating and skewing a DIV element. In this case it is used to rotate the clock hands to the correct angles; the CSS below puts the hour hand at 3 o’clock:
#clock img[src*='hour'] {
-webkit-transform: rotate(90deg);
}
The transition property creates an animation of a specified property between two values when triggered, for instance fading the opacity on a DIV element from 1 to 0 — triggered using the :hover pseudo class. Transition duration and the transition timing function (e.g. linear) should also be set, amongst other optional properties. In this example the transition is from one transformation angle to another with durations that match the appropriate clock hand, so the second hand takes 60 seconds to complete a 360 degree rotation. The transition is triggered using the :target pseudo element — if the URI contains the ‘clock’ fragment then the time piece shall start ticking.
#clock img[src*='second'] {
/* -webkit-transition: property duration timing-function */
-webkit-transition: -webkit-transform 60s linear;
}
#clock:target img[src*='second'] {
-webkit-transform: rotate(360deg);
}
The above transition lasts only one rotation but by altering the duration length and degree of rotation in accordance the second hand can keep on going (e.g. 600 seconds and 3600 degrees rotation gives a battery life of 10 minutes), a fairly safe assumption that users will not stay on the page for too long.
#clock img[src*='second'] {
-webkit-transition: -webkit-transform 600000s linear;
}
#clock:target img[src*='second'] {
-webkit-transform: rotate(3600000deg);
}
#clock img[src*='minute'] {
-webkit-transition: -webkit-transform 360000s linear;
}
#clock:target img[src*='minute'] {
-webkit-transform: rotate(36000deg);
}
Grab the current time
Although the animation works beautifully, CSS alone is not capable of obtaining the current time. To start the clock at the correct time a dynamic transformation needs to be applied to the clock hand containers, this is easiest done with inline styles and can be set in any number of ways by the backend when the page loads, thereby eradicating any need for JavaScript.
Alternatively, if you’ve no objections to using JavaScript, I’ve created a small startClock() function to do the job (albeit using Prototype 1.6.0.3 for my own convenience):
function startClock() {
var angle = 360/60;
var date = new Date();
var hour = date.getHours();
if(hour > 12) {
hour = hour - 12;
}
var minute = date.getMinutes();
var second = date.getSeconds();
var hourAngle = (360/12)*hour + (360/(12*60))*minute;
$('minute').setStyle('-webkit-transform: rotate('+angle*minute+'deg)');
$('second').setStyle('-webkit-transform: rotate('+angle*second+'deg)');
$('hour').setStyle('-webkit-transform: rotate('+hourAngle+'deg)');
}
A word of warning — applying the inline style directly to the image will override the transition effects defined in the CSS file.
Discussion
In Google Chromium (for linux) works fine!
You can add Google Chrome to your compatible browsers
Works in Safari 3.2.1 on a Mac, cool !
FF 3.1 also has css transforms https://developer.mozilla.org/web-tech/2008/09/12/css-transforms/
This work also on Safari 3.1.2 (525.21)
Cool!
Page zooming doesn’t work on Mac (Safari 3.2.1), though.
Sweet! Works in Safari 4 BETA. I’m going to try this out myself!
Wow, nice clock. I made a similar one last year — using the aforementioned CSS transforms with a touch of JavaScript — see:
http://www.cuppadev.co.uk/oldbrew/an-analogue-clock-using-safari-transforms/
Very cool! Gotta be careful with this stuff, tho — when I ran it in Chrome on WinXP on a Dell Inspiron 6000, it chewed up 55% of CPU.
You could try to integrate rotating for older browsers by using: http://wilq32.googlepages.com/wilq32.rollimage222
I used a similar technique here:
http://ryancannon.com/mtg/hi/
to keep time, but mine is intended for longer periods. One thing to note: you must always increment the transform up. If, for example, you set the hands at noon to 0deg when they were at 359deg a minute before hand, your arms will rotate backwards.
A bit of a pain, and I haven’t found a work around, other than incrementing to infinity.
You get an interesting effect when you try and select the image in chrome, crazy shapes!
This is amazing! Had no idea you could do anything like this in CSS, will have to give it a go!
I saw the source code of demo page that contains the link ‘start’ to start the clock but How to start the clock automatically on page load ?? Plz mail me.…
Hello,
This is so interesting!! Sorry for my bad english, i am french and i did a translation of this page in my blog.
Is it ok for you? I mean you allow me to share what i understand with others.
Here is the link : http://www.ghislaine-wabstemer.com/2011/01/trouvailles-wabstemer/
thanks,
Very creative nice work;)
i go through the tutorial but clock is not working…
can you help me on that…
It isnt working in latest chrome, help?
how can I do start the clock without url : “clock.html#clock” –> I want to url only clock.html not #clock ? how can we doing ?
i have a project i’m looking for a developer for, which involves development of analogue clocks with some features a little beyond your example here… its for the playback on SIgnage Media players… are you available for freelance work…?
very beautiful!
Ctrl+A and you can see the image rotating
Nice One,
But how can I do start the clock without url : “clock.html#clock” –> I want to url only clock.html not #clock ? how can we doing ?
Comment