Home / Snippets / Animation & Motion /
Steps easing comparison
Compare steps() easing values side by side — discrete jumps vs smooth linear motion.
Quick implementation
@keyframes slide {
to { transform: translateX(100%); }
}
/* Stepped — 4 discrete jumps */
.steps-4 {
animation: slide 2s steps(4) infinite alternate;
}
/* Stepped — 8 discrete jumps */
.steps-8 {
animation: slide 2s steps(8) infinite alternate;
}
/* Stepped — 12 discrete jumps */
.steps-12 {
animation: slide 2s steps(12) infinite alternate;
}
/* Single jump at start and end */
.steps-jump-both {
animation: slide 2s steps(1, jump-both) infinite alternate;
}
/* Smooth linear for comparison */
.linear {
animation: slide 2s linear infinite alternate;
}
@media (prefers-reduced-motion: reduce) {
.steps-4,
.steps-8,
.steps-12,
.steps-jump-both,
.linear {
animation: none;
}
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer building a CSS animation demo page.
Goal: A side-by-side visual comparison of CSS steps() easing values — no JavaScript.
Technical constraints:
- Use @keyframes with transform: translateX(100%) for the sliding motion.
- Show at least 4 steps() variants: steps(4), steps(8), steps(12), steps(1, jump-both).
- Include a linear variant as a baseline comparison.
- Label each row clearly with the timing function used.
- Use oklch() for all colors, not hex or rgba().
- Include @media (prefers-reduced-motion: reduce) to pause all animations.
Framework variant (pick one):
A) Vanilla CSS with modifier classes (.steps-4, .steps-8, etc.) applied to a shared element.
B) React component — render rows dynamically from an array of timing function strings.
Edge cases to handle:
- Bars must not overflow their track container (use overflow: hidden on the track).
- Animation should alternate (forward and back) to loop visibly without a jump cut.
- steps(1, jump-both) jumps at both 0% and 100% — make this visually apparent.
Return HTML and CSS.
Why this matters in 2026
The steps() timing function is the backbone of sprite-sheet animations, typewriter effects, and progress indicators with discrete states. Most developers reach for linear or ease by default — understanding the full range of step configurations unlocks a class of animation that feels intentionally mechanical rather than accidentally choppy.
The logic
The steps(n) function divides the animation duration into n equal intervals, jumping between them instantaneously. steps(4) creates 4 visible positions; steps(12) creates 12. The optional second argument controls where the jump occurs in each interval: jump-start (default) jumps at the beginning, jump-end at the end, and jump-both adds a jump at both endpoints — useful for centering a sprite in its cell.
All bars share the same @keyframes slide declaration. Only the animation-timing-function differs, making this a pure easing comparison with no other variables.
Accessibility & performance
@media (prefers-reduced-motion: reduce) disables all five animations for users with vestibular disorders. Because the animation uses only transform: translateX, it runs entirely on the GPU compositor — no layout or paint is triggered. The infinite alternate fill prevents the jarring reset that would occur with infinite alone.