How to Make a Digital Clock with jQuery and CSS3

How to Make a Digital Clock with jQuery and CSS3

It all started last week when I saw this pretty dribbble shot. I immediately felt the urge to convert it into a working clock and share it with Tutorialzine’s readers. If you’d like to learn how I made it, read on!

Update: The second part of this tutorial is now live! There we are adding support for setting alarms with HTML5 audio. Read it here.

The Markup

The clock doesn’t need a lot of HTML. This is because a large part of it, like the names of the weekdays and the code for the digits, is generated dynamically. Here is the markup that you need to have on your page to use the clock:

index.html

<div id="clock" class="light">
	<div class="display">
		<div class="weekdays"></div>
		<div class="ampm"></div>
		<div class="alarm"></div>
		<div class="digits"></div>
	</div>
</div>

The main element, the #clock div, contains the .display, which in turn holds the list of weekdays, AM/PM label the alarm icon and the time. And here is the generated markup for one of the digits:

<div class="zero">
	<span class="d1"></span>
	<span class="d2"></span>
	<span class="d3"></span>
	<span class="d4"></span>
	<span class="d5"></span>
	<span class="d6"></span>
	<span class="d7"></span>
</div>

The .digits element will contain 6 of these divs with spans, one for each digit of the time. As you can see from the fragment above, these divs get a class name from zero to nine (more on that in a second), and contain seven span elements with unique classes. These spans are the segments of the digits, like in the digital clocks of old:

The Digits Explained

The Digits Explained

They are styled entirely with CSS and are set to opacity:0 by default. The class assigned to their parent div is what makes them visible. Here is the CSS for the zero:

assets/css/styles.css

/* 0 */

#clock .digits div.zero .d1,
#clock .digits div.zero .d3,
#clock .digits div.zero .d4,
#clock .digits div.zero .d5,
#clock .digits div.zero .d6,
#clock .digits div.zero .d7{
	opacity:1;
}

All segments are visible, except for the middle one (otherwise it would be an 8). I have added a CSS3 transition property to all these spans, which animates the opacity when switching between numbers.

There is a lot of other CSS in the stylesheet, but I will not be presenting it here. I believe the best way to learn how the CSS works is by inspecting the live-working code of the demo in Firebug, Chrome’s Inspector or the developer tools of your browser of choice.

The Dark Theme

The Dark Theme

The jQuery Code

To make the clock work, we will have to use jQuery to generate the markup for each of the digits, and set a timer to update the classes every second. To make our lives easier, we will use the moment.js library (quick tip) to compensate for the lacking JavaScript native date and time functions.

assets/js/script.js

$(function(){

	// Cache some selectors

	var clock = $('#clock'),
		alarm = clock.find('.alarm'),
		ampm = clock.find('.ampm');

	// Map digits to their names (this will be an array)
	var digit_to_name = 'zero one two three four five six seven eight nine'.split(' ');

	// This object will hold the digit elements
	var digits = {};

	// Positions for the hours, minutes, and seconds
	var positions = [
		'h1', 'h2', ':', 'm1', 'm2', ':', 's1', 's2'
	];

	// Generate the digits with the needed markup,
	// and add them to the clock

	var digit_holder = clock.find('.digits');

	$.each(positions, function(){

		if(this == ':'){
			digit_holder.append('<div class="dots">');
		}
		else{

			var pos = $('<div>');

			for(var i=1; i<8; i++){
				pos.append('<span class="d' + i + '">');
			}

			// Set the digits as key:value pairs in the digits object
			digits[this] = pos;

			// Add the digit elements to the page
			digit_holder.append(pos);
		}

	});

	// Add the weekday names

	var weekday_names = 'MON TUE WED THU FRI SAT SUN'.split(' '),
		weekday_holder = clock.find('.weekdays');

	$.each(weekday_names, function(){
		weekday_holder.append('<span>' + this + '</span>');
	});

	var weekdays = clock.find('.weekdays span');

	// Run a timer every second and update the clock

	(function update_time(){

		// Use moment.js to output the current time as a string
		// hh is for the hours in 12-hour format,
		// mm - minutes, ss-seconds (all with leading zeroes),
		// d is for day of week and A is for AM/PM

		var now = moment().format("hhmmssdA");

		digits.h1.attr('class', digit_to_name[now[0]]);
		digits.h2.attr('class', digit_to_name[now[1]]);
		digits.m1.attr('class', digit_to_name[now[2]]);
		digits.m2.attr('class', digit_to_name[now[3]]);
		digits.s1.attr('class', digit_to_name[now[4]]);
		digits.s2.attr('class', digit_to_name[now[5]]);

		// The library returns Sunday as the first day of the week.
		// Stupid, I know. Lets shift all the days one position down, 
		// and make Sunday last

		var dow = now[6];
		dow--;

		// Sunday!
		if(dow < 0){
			// Make it last
			dow = 6;
		}

		// Mark the active day of the week
		weekdays.removeClass('active').eq(dow).addClass('active');

		// Set the am/pm text:
		ampm.text(now[7]+now[8]);

		// Schedule this function to be run again in 1 sec
		setTimeout(update_time, 1000);

	})();

	// Switch the theme

	$('a.button').click(function(){
		clock.toggleClass('light dark');
	});

});

The most important piece of code here is the update_time function. Inside it, we get the current time as a string, and use it to fill in the elements of the clock and to set the correct classes to the digits.

With this our digital clock is ready! Check the next part, where we adding support for setting alarms and playing them back with HTML5 audio.

Join our newsletter and get our PSDs!17,425 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and publishes new tutorials weekly.

21 Comments

  1. Giang Pi says:

    Cool, thanks Martin Angelov

  2. Benz says:

    Good Job! Thank for your sharing! I like this!

  3. Pushker says:

    awesome, always learns new things here

  4. Matteo says:

    You're a genius.

  5. Lillo says:

    WOW it's wonderfull!!

  6. NICO says:

    Incredible. Dont know how you do this, but EVERYTHING you post here is brilliance and quality,, Martin. Thx for all of your work, man!

  7. Alex Williams says:

    Awesome script, one of the most impressive things I have seen in a while. Looks really good.

  8. Cool Script.. Really Awesome :)

  9. Alexander says:

    Great tutorial! Thanks!

  10. James Kolsby says:

    This is incredible, but why did you decide to create separate elements for each part of the digit rather than just having ten different vector files for each digit?

    1. Martin Angelov says:

      I took it as a challenge. Having each segment of the digits as separate elements opens the doors to interesting CSS3 transformations when switching from one digit to the next. You could use 3D transforms and rotations, color changes, opacity for each part individually, which would be impossible with images.

      To be fair the easiest way would probably be to simply use or make a web font and include that in the page.

  11. Dewark says:

    Good work, as usual.

    Great thanks Martin, this is the best tutorial site I've seen ever.

  12. ezybusy says:

    how to change the font size ??? i want to make it smaller

  13. Awesome Martin, much appreciate your work. Always comes to your blog whenever i need to learn something new.

  14. Nelson says:

    Amazing Stuff man. will surely integrate this on a future project :)

  15. Jean Rodriguez says:

    Hello, can set this clock to work with diferents times, example, can i display the time of New York, the time in london, or california? Thanks.

  16. Damien Gosset says:

    nice tutorial, thanks!
    just a few CSS tweaks, and I turned it to a binary clock

    1. Martin Angelov says:

      This is very cool! Great work.

      1. Damien Gosset says:

        thank you :)

  17. Rahul says:

    Very cool stuff! Can we have similar post on AngularJS? a small comparison between the two[AngularJS and jQuery] would be even better.

  18. Sprint says:

    Great tutorial and awesome clock! Thank you very much!

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links