What if I told you that we can make a timer without using
To make the timer, we'll need four CSS classes (Please note that we could create a minimal example with only two classes (
.timer--running), but it is pretty limiting and therefore we are going to skip it.) :
.timer- initial styles
.timer--running- starts the animation
.timer--paused- pauses the animation (can only be used in combination with
.timer--done- final state of the animation
We'll start a timer by adding a
.timer--running class. In the case that we are restarting it, we also need to remove the
// Start the timer
'timer--running'; // $timer is a reference to the timer's DOM element
To pause it we'll add
.timer--paused class. Resume it by removing the class.
// Toggle the pause class
animationend event is triggered, we know the animation is done, so we need to add
.timer--done and to remove
// Update classes so the timer can be restarted
When we put it all together, we get a minimal working example:
Code is also available on CodePen for you to play with.
This timer works similarly to
setTimeout, but it comes with it's own animation loop and an easy way to pause it.
To get a behavior similar to
setInterval we are going to switch to animationiteration instead of
For this demo, we'll change our CSS to create a small stopwatch:
Again, code is available on CodePen.
If we need multiple timers, we can chain them. When a timer finishes, we need to trigger the next one:
The mandatory demo on CodePen.
The example above looks like a pagination for an autoplaying carousel, but we still need to add a way to jump to a certain timer/slide.
The main thing is that once we jump to a timer, we need to make sure that all of the previous timers in the pagination are set to the end state, while the next timers are set to the init state.
Once we do that, we get an autoplaying carousel:
This CodePen was my initial playground, so it may contain some leftovers and it might not be the cleanest code you have ever read. Sorry for that. I hope it is still fairly easy to follow.
It wasn't necessary for the carousel example, but the main limitation is the inability to precisely track the timer's progress.
But please be aware that some older browsers do not support Web Animations API. For example, Safari added support in 2020, so if you need to support older browsers using animations with CSS classes might be better as they are supported since IE10.
There you have it, timers using CSS animations.
CSS animations weren't made for this use case, but if you ask me, it is a great little hack and for certain problems they offer a very elegant solution.
We can even use
animation-timing-function: steps(n) to add discrete steps to our timer: