Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
The CSS steps()
function let us divide the progress of an animation or transition into a specified number of equal-length intervals or steps, making the animation take constant jumps between steps.
.bar-1 {
animation-timing-function: steps(10);
}
.bar-2 {
animation-timing-function: steps(10, jump-start);
}
The steps()
function is defined in the CSS Easing Functions Level 2 specification, and it’s one of the 3 CSS easing functions.
Syntax
The CSS steps()
function only works with the animation-timing-function
and transiton-timing-function
CSS properties. Its syntax is as follows:
steps( <integer>, <step-position>? )
<step-position> = jump-start | jump-end | jump-none | jump-both | start | end
Arguments
/* Only steps */
steps(2);
steps(5);
steps(10);
/* Step positions */
steps(10, jump-start);
steps(10, jump-end);
steps(10, jump-none);
steps(10, jump-both);
The steps()
function takes only two arguments. The first argument determines the number of steps the animation will be divided into. It has to be an integer greater than 0
, except when <step-position>
is set to jump-none
, in which case it must be greater than 1
.
The <step-position>
is a bit more extensive. It offers six different options that can be selected, but only four are distinct since start
and end
are equivalent to jump-start
and jump-end
, respectively.
The four distinct options are:
jump-start
orstart
: The animation jumps to the next step at the beginning of each interval. The first step happens immediately, so the animation starts at the first keyframe value right away.jump-end
orend
: The animation holds the current value until the end of each interval, then jumps to the next step. The first step only happens after the first interval, delaying the initial change.jump-none
: The start and end of the animation are not skipped. The animation moves to the next step at the start of each interval, with a smooth transition within steps.jump-both
: Both the start and end of the animation are skipped. The animation jumps at both the start and end of each interval, creating the most abrupt changes. It moves to the next step immediately and holds until the next jump.
Basic usage
You’ve most likely come across a website with its text coming in like it’s being typed in real-time, known as the typewriting effect. In fact, we’ve covered it before in another article! Let’s break down how this works with the steps()
function.
.typewriter {
font-family: "Courier New", monospace;
overflow: hidden;
white-space: nowrap;
border-right: 3px solid #333;
width: 0;
animation: typing 4s steps(28) forwards, blink 0.8s step-end infinite;
}
@keyframes typing {
to {
width: 28ch; /* 28 characters wide */
}
}
In this example, we first set the width of the text container to 0
, and then use the number of characters as the number of steps and animation duration. Using the ch
unit, which is equal to the width of one character, we reveal one character at a time. This makes it look as if it’s typed in real-time. The blinking cursor at the end further cements the idea of a typewriter.
steps()
Example: Heartbeat with Another animation we can achieve with the steps()
function is a simulated heartbeat effect. Taking inspiration from Kevin Powell’s short on timing function tips, we use a simple heart shape SVG and make it beat by scaling it up and down.
svg {
animation: heartbeat 1s infinite steps(4);
}
@keyframes heartbeat {
0% {
scale: 1;
}
45% {
scale: 1.1;
}
65% {
scale: 1.2;
}
100% {
scale: 1;
}
}
The SVG is a simple heart shape, so we only need to add the animation and bring the heart to life. Between 45% and 65%, the heart’s size increased by 0.1
and 0.2
, respectively, making the heartbeat more realistic.
steps()
Example: Clock counter with Let’s animate the seconds hand of a clock with the steps()
function. Mind you, the steps()
function is not the only easing function used here, but for the seconds hand, it is, and that is our focus.
Analogue clock
.second-hand {
animation: hand-move 60s steps(60) infinite;
}
@keyframes hand-move {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
The analogue clock is quite easy because it only requires rotating the second hand 360 degrees, infinitely, in 60 steps, and at 60 seconds per interval.
The minutes and hours hands of the analogue clock also move, but linearly (which is not our focus), and their duration is set to 60 × 60 for minutes, and 60 × 60 × 12 for a complete rotation that takes one hour to complete.
Digital clock
.seconds-display::before {
content: "00";
animation: seconds-count 60s steps(60) infinite;
}
@keyframes seconds-count {
0% {
content: "00";
}
1.67% {
content: "01";
}
3.33% {
content: "02";
}
5% {
content: "03";
}
/* up until 60s */
}
The digital clock was quite tricky compared to the analog clock. It involved using the CSS content
property for the seconds hand and manipulating the value at every %
equivalent to its 60-second counterpart.
Specification
The steps()
function is defined in the CSS Easing Functions Level 2 specification, which is currently in Editor’s Draft.
Browser support
The CSS steps()
function is fully supported on all browsers. However, it’s important to wrap your animations with the CSS media prefers-reduced-motion: no-preference
for users who might not like unnecessary motions on a website for one reason or another.
@media (prefers-reduced-motion: no-preference) {
/* your animation */
}