Introduction
In this article we'll create a stop watch using HTML5 and CSS3. We will only focus on CSS3 keyframe animation and there will be the 3 states start, stop and reset. Start will start the stopwatch, stop will stop the stopwatch and reset can reset the stopwatch.
The core logic is very simple, we will use a simple div container to contain some numbers and that will be move upside using key frame animation.
First create a div (with the containing number) using the following HTML Code:
- <!doctype html>
- <html>
- <head>
- <title>Stopwatch</title>
- <link rel="stylesheet" href="Style.css"/>
- </head>
- <body>
- <div class="number">0 1 2 3 4 5 6 7 8 9</div>
- </body>
- </html>
The following is the output of the preceding code:
Now we align the numbers vertically by reducing the width of the container. So create a CSS file (styles.css) and write the following code inside that CSS file.
- * {
- margin: 0; padding: 0;
- }
-
- .numbers {
- width: 10px;
- }
With the preceding code your output numbers will be aligned vertically such as in the following:
Now I am using some digital fonts that you can download form the link
ds-digi.font. Use the following CSS code to modify the font-family.
- .number {
- width: 10px;
- font-family: digital, arial, verdana;
- font-size:50px;
- }
- @font-face {
- font-family: 'digital';
- src: url('DS-DIGI.TTF');
- }
With the preceding code the output will be as in the following:
Let's wrap up the numbers in a box to display 1 digit only. So in the HTML file put your number div in another box div. The code is as in the following:
- <div class="box">
- <div class="number">0 1 2 3 4 5 6 7 8 9</div>
- </div>
Now apply the following CSS rules to display only one digit:
- .box{
- width:40px;
- height:40px;
- border: 1px solid #000;
- font-size:50px;
- overflow:hidden;
- }
-
- .number {
- width: 40px;
- line-height:40px;
- font-family: digital, arial, verdana;
- text-align: center;
- }
The following the output of the preceding code:
Let's animate the digit since that is the main task of this article. The logic for the animation is to alter the value of the top absolute position from 0 to -400px because the height of the box is 40 px and we have 0 to 9, in other words a total of 10 numbers so (40*10=400) we will alter the top from 0 to -400px. Provide the following code for the style.css file.
- .box{
- width:40px;
- height:40px;
- border: 1px solid #000;
- font-size:50px;
- overflow:hidden;
-
- position: relative;
- }
-
- .number {
- width: 40px;
- line-height:40px;
- font-family: digital, arial, verdana;
- text-align: center;
-
- position: absolute;
- top: 0;
- left: 0;
-
- -webkit-animation: moveup 1s steps(10, end) infinite;
- animation: moveup 1s steps(10, end) infinite;
- }
- @-webkit-keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
The following is the output of the preceding code:
You can see that the digits are swapping instead of moving up pixel by pixel.
Now create some more div for 2 for hours, 2 for minutes, 2 for seconds and 3 for mili-seconds in your HTML file.
- <!doctype html>
- <html>
- <head>
- <title>Stopwatch</title>
- <link rel="stylesheet" href="Style.css"/>
- </head>
- <body>
- <div class="stopwatch">
- <div class="box">
-
- <div class="number tensPlaceHours">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number onesPlaceHours">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
-
- <div class="box">
- <div class="number tensPlaceMinutes">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceMinutes">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
-
- <div class="box">
- <div class="number tensPlaceSeconds">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceSeconds">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
-
- <div class="box">
- <div class="number onesPlaceMiliSeconds">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number tensPlaceMiliSeconds">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number hundredsPlaceMiliSeconds">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- </div>
- </body>
- </html>
The following is the output using the preceding code:
Now float all the boxes left so in the Style.css for the box class selector provide the float:left property.
- .box{
- width:40px;
- height:40px;
- border: 1px solid #000;
- font-size:50px;
- overflow:hidden;
-
- position: relative;
- float:left;
- }
After applying the float:left property the output will be as in the following:
Here the minutes and seconds max values will be 60 so we need to create two animations, one that will have 10 steps and 10 digits and the other one with 6 steps and only 6 digits. Use the following CSS code for this:
- * {
- margin: 0; padding: 0;
- }
- .box{
- width:40px;
- height:40px;
- border: 1px solid #000;
- font-size:50px;
- overflow:hidden;
-
- position: relative;
- float:left;
- }
-
- .number {
- width: 40px;
- line-height:40px;
- font-family: digital, arial, verdana;
- text-align: center;
-
- position: absolute;
- top: 0;
- left: 0;
-
- -webkit-animation: moveup 1s steps(10, end) infinite;
- animation: moveup 1s steps(10, end) infinite;
- }
-
- .moveuptens{
- -webkit-animation: moveuptens 1s steps(10, end) infinite;
- animation: moveuptens 1s steps(10, end) infinite;
- }
- .moveupsix{
- -webkit-animation: moveupsix 1s steps(6, end) infinite;
- animation: moveupsix 1s steps(6, end) infinite;
- }
-
- @-webkit-keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
-
- @keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
- @font-face {
- font-family: 'digital';
- src: url('DS-DIGI.TTF');
- }
Now after creating the preceding 2 animations apply a CSS class to the HTML as in the following code:
- <div class="stopwatch">
- <div class="box">
- <div class="number tensPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number onesPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceMinutes moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceMinutes moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceSeconds moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
-
- <div class="box">
- <div class="number
MiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number tensPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number
MiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- </div>
Now your output is as in the following:
Now we need to sync the animation speed with the time speed. So apply the following properties:
- .onesPlaceSeconds {
- animation-duration: 10s;
- -webkit-animation-duration: 10s;
- }
- .tensPlaceSeconds {
- animation-duration: 60s;
- -webkit-animation-duration: 60s;
- }
-
- .hundredsPlaceMiliSeconds {
- animation-duration: 1s;
- -webkit-animation-duration: 1s;
- }
-
- .tensPlaceMiliSeconds {
- animation-duration: 0.1s;
- -webkit-animation-duration: 0.1s;
- }
- .hundredsPlaceMiliSeconds {
- animation-duration: 0.01s;
- -webkit-animation-duration: 0.01s;
- }
-
- .onesPlaceMinutes {
- animation-duration: 600s;
- -webkit-animation-duration: 600s;
- }
- .tensPlaceMinutes {
- animation-duration: 3600s;
- -webkit-animation-duration: 3600s;
- }
-
- .onesPlaceHours {
- animation-duration: 36000s;
- -webkit-animation-duration: 36000s;
- }
- .tensPlaceHours {
- animation-duration: 360000s;
- -webkit-animation-duration: 360000s;
- }
The following is the output of the preceding code:
You can see that now the stop watch is looking good. Now to add some styles to the stop watch. I am modifying the HTML and CSS now for the style.
HTML File:
- <!doctype html>
- <html>
- <head>
- <title>Stopwatch</title>
- <link rel="stylesheet" href="Style.css"/>
- </head>
- <body>
-
- <div class="MainContainer">
- <div class="stopwatch">
- <div class="box">
- <div class="number tensPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number onesPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceMinutes moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceMinutes moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceSeconds moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
-
- <div class="box">
- <div class="number onesPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number tensPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number hundredsPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- </div>
- </div>
- </body>
- </html>
CSS File:
- * {
- margin: 0;
- padding: 0;
- }
-
- body{
- background:url(images.jpg);
- }
-
- .MainContainer{
- padding:200px;
- text-align:center;
- }
-
- .stopwatch{
- padding:10px;
- background: linear-gradient(top, #222, #444);
- overflow: hidden;
- display:inline-block;
- border: 7px solid #eeeeee;
- border-radius:20px;
-
- box
- }
-
- .box{
- width:40px;
- height:40px;
- font-size:50px;
- overflow:hidden;
-
- position: relative;
- float:left;
- }
-
- .number {
- width: 40px;
- line-height:40px;
- font-family: digital, arial, verdana;
- text-align: center;
- color:#fff;
-
- position: absolute;
- top: 0;
- left: 0;
-
- -webkit-animation: moveup 1s steps(10, end) infinite;
- animation: moveup 1s steps(10, end) infinite;
- }
-
- .moveuptens{
- -webkit-animation: moveuptens 1s steps(10, end) infinite;
- animation: moveuptens 1s steps(10, end) infinite;
- }
- .moveupsix{
- -webkit-animation: moveupsix 1s steps(6, end) infinite;
- animation: moveupsix 1s steps(6, end) infinite;
- }
-
- .onesPlaceSeconds {
- animation-duration: 10s;
- -webkit-animation-duration: 10s;
- }
- .tensPlaceSeconds {
- animation-duration: 60s;
- -webkit-animation-duration: 60s;
- }
-
- .onesPlaceMiliSeconds {
- animation-duration: 1s;
- -webkit-animation-duration: 1s;
- }
-
- .tensPlaceMiliSeconds {
- animation-duration: 0.1s;
- -webkit-animation-duration: 0.1s;
- }
- .hundredsPlaceMiliSeconds {
- animation-duration: 0.01s;
- -webkit-animation-duration: 0.01s;
- }
-
- .onesPlaceMinutes {
- animation-duration: 600s;
- -webkit-animation-duration: 600s;
- }
- .tensPlaceMinutes {
- animation-duration: 3600s;
- -webkit-animation-duration: 3600s;
- }
-
- .onesPlaceHours {
- animation-duration: 36000s;
- -webkit-animation-duration: 36000s;
- }
- .tensPlaceHours {
- animation-duration: 360000s;
- -webkit-animation-duration: 360000s;
- }
-
- @-webkit-keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
-
- @keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
- @font-face {
- font-family: 'digital';
- src: url('DS-DIGI.TTF');
- }
After applying some style the output of the stop watch is as in the following:
Now I am adding 3 radio buttons t6o start, stop and reset the stopwatch. In other words these buttons will control the stop watch.
HTML Code:
- <!doctype html>
- <html>
- <head>
- <title>Stopwatch</title>
- <link rel="stylesheet" href="Style.css"/>
- </head>
- <body>
-
- <div class="MainContainer">
- <input id="start" name="controls" type="radio" />
- <input id="stop" name="controls" type="radio" />
- <input id="reset" name="controls" type="radio" />
- <div class="stopwatch">
- <div class="box">
- <div class="number tensPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number onesPlaceHours moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceMinutes moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceMinutes moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number tensPlaceSeconds moveupsix">0 1 2 3 4 5 6</div>
- </div>
- <div class="box">
- <div class="number onesPlaceSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
-
- <div class="box divider">
- <div class="number">:</div>
- </div>
-
- <div class="box">
- <div class="number onesPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number tensPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- <div class="box">
- <div class="number hundredsPlaceMiliSeconds moveuptens">0 1 2 3 4 5 6 7 8 9</div>
- </div>
- </div>
-
- <div id="stopwatch_controls">
- <label for="start">Start</label>
- <label for="stop">Stop</label>
- <label for="reset">Reset</label>
- </div>
- </div>
- </body>
- </html>
Now apply some CSS to style the controls and control's label and also control the animation with that:
- * {
- margin: 0;
- padding: 0;
- }
-
- body{
- background:url(images.jpg);
- }
-
- .MainContainer{
- padding:200px;
- text-align:center;
- }
-
- .stopwatch{
- padding:10px;
- background: linear-gradient(top, #222, #444);
- overflow: hidden;
- display:inline-block;
- border: 7px solid #eeeeee;
- border-radius:20px;
-
- box
- }
-
- .box{
- width:40px;
- height:40px;
- font-size:50px;
- overflow:hidden;
-
- position: relative;
- float:left;
- }
-
- .number {
- width: 40px;
- line-height:40px;
- font-family: digital, arial, verdana;
- text-align: center;
- color:#fff;
-
- position: absolute;
- top: 0;
- left: 0;
-
- -webkit-animation: moveup 1s steps(10, end) infinite;
- animation: moveup 1s steps(10, end) infinite;
- }
-
- #stopwatch_controls label {
- cursor: pointer;
- padding: 5px 10px;
- background: #eeeeee;
- font-family: arial, verdana, tahoma;
- font-size: 20px;
- border-radius: 0 0 3px 3px;
- }
-
- input[name="controls"] {
- display: none
- }
-
- #stop:checked~.stopwatch .number {
- animation-play-state: paused;
- -webkit-animation-play-state: paused;
- }
- #start:checked~.stopwatch .number {
- animation-play-state: running;
- -webkit-animation-play-state: running;
- }
- #reset:checked~.stopwatch .number {
- animation: none;
- -webkit-animation: none;
- }
-
- .moveuptens{
- -webkit-animation: moveuptens 1s steps(10, end) infinite;
- animation: moveuptens 1s steps(10, end) infinite;
-
- animation-play-state: paused;
- -webkit-animation-play-state: paused;
- }
- .moveupsix{
- -webkit-animation: moveupsix 1s steps(6, end) infinite;
- animation: moveupsix 1s steps(6, end) infinite;
-
- animation-play-state: paused;
- -webkit-animation-play-state: paused;
- }
-
- .onesPlaceSeconds {
- animation-duration: 10s;
- -webkit-animation-duration: 10s;
- }
- .tensPlaceSeconds {
- animation-duration: 60s;
- -webkit-animation-duration: 60s;
- }
-
- .onesPlaceMiliSeconds {
- animation-duration: 1s;
- -webkit-animation-duration: 1s;
- }
-
- .tensPlaceMiliSeconds {
- animation-duration: 0.1s;
- -webkit-animation-duration: 0.1s;
- }
- .hundredsPlaceMiliSeconds {
- animation-duration: 0.01s;
- -webkit-animation-duration: 0.01s;
- }
-
- .onesPlaceMinutes {
- animation-duration: 600s;
- -webkit-animation-duration: 600s;
- }
- .tensPlaceMinutes {
- animation-duration: 3600s;
- -webkit-animation-duration: 3600s;
- }
-
- .onesPlaceHours {
- animation-duration: 36000s;
- -webkit-animation-duration: 36000s;
- }
- .tensPlaceHours {
- animation-duration: 360000s;
- -webkit-animation-duration: 360000s;
- }
-
- @-webkit-keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveup {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
-
- @keyframes moveuptens {
- 0% {top: 0px;}
- 100%{top:-400px;}
- }
-
- @-webkit-keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
-
- @keyframes moveupsix {
- 0% {top: 0px;}
- 100%{top:-240px;}
- }
-
- @font-face {
- font-family: 'digital';
- src: url('DS-DIGI.TTF');
- }
Final Output
Happy Coding. :)