A walk cycle played frame by frame: an eight frame strip slides behind a window with steps(8), so it jumps a whole frame at a time. The ground scrolls smoothly underneath for contrast.
Also known as: css steps() animation, frame by frame animation css, sprite animation css.
<div class="kfa-sprite-sheet-steps"><svg class="kfa-sprite-sheet-steps-strip" viewBox="0 0 320 40" aria-hidden="true"><path opacity="0.5" d="M20 21.8L20 29.8L20 37.8M20.8 12.3L20.8 18.3L24.3 22.5M60 22.2L57.5 29.7L55 37.3M60.8 12.7L62.6 18.4L67.2 21.4M100 23L96.5 30.2L93 37.4M100.8 13.5L103.2 19L108.2 21.4M140 22.2L137.5 29.7L131 34.5M140.8 12.7L142.6 18.4L147.2 21.4M180 21.8L180 29.8L173.9 34.9M180.8 12.3L180.8 18.3L184.3 22.5M220 22.2L222.5 29.7L220.2 37.4M220.8 12.7L219 18.4L221.2 23.5M260 23L263.5 30.2L267 37.4M260.8 13.5L258.4 19L259.9 24.3M300 22.2L302.5 29.7L305 37.3M300.8 12.7L299 18.4L301.2 23.5" /><path d="M20 21.8L20 29.8L13.9 34.9M20.8 12.3L20.8 18.3L24.3 22.5M20 21.8L20.8 10.8M60 22.2L62.5 29.7L60.2 37.4M60.8 12.7L59 18.4L61.2 23.5M60 22.2L60.8 11.2M100 23L103.5 30.2L107 37.4M100.8 13.5L98.4 19L99.9 24.3M100 23L100.8 12M140 22.2L142.5 29.7L145 37.3M140.8 12.7L139 18.4L141.2 23.5M140 22.2L140.8 11.2M180 21.8L180 29.8L180 37.8M180.8 12.3L180.8 18.3L184.3 22.5M180 21.8L180.8 10.8M220 22.2L217.5 29.7L215 37.3M220.8 12.7L222.6 18.4L227.2 21.4M220 22.2L220.8 11.2M260 23L256.5 30.2L253 37.4M260.8 13.5L263.2 19L268.2 21.4M260 23L260.8 12M300 22.2L297.5 29.7L291 34.5M300.8 12.7L302.6 18.4L307.2 21.4M300 22.2L300.8 11.2" /><g fill="currentColor" stroke="none"><circle cx="21.2" cy="6.4" r="3.6" /><circle cx="61.2" cy="6.8" r="3.6" /><circle cx="101.2" cy="7.6" r="3.6" /><circle cx="141.2" cy="6.8" r="3.6" /><circle cx="181.2" cy="6.4" r="3.6" /><circle cx="221.2" cy="6.8" r="3.6" /><circle cx="261.2" cy="7.6" r="3.6" /><circle cx="301.2" cy="6.8" r="3.6" /></g></svg></div>
.kfa-sprite-sheet-steps {
--c: var(--kfa-color, #3b82f6);
font-size: var(--kfa-size, 16px);
display: grid;
place-items: center;
width: 5.5em;
height: 5.5em;
border-radius: 1em;
background: var(--c);
color: #fff;
font-family: system-ui, sans-serif;
font-weight: 700;
box-shadow: 0 0.6em 1.4em -0.6em color-mix(in srgb, var(--c) 70%, transparent);
position: relative;
overflow: hidden;
}
/* the sheet: eight 40 unit frames in a row, one frame wide per box width */
.kfa-sprite-sheet-steps-strip {
position: absolute;
top: 0;
left: 0;
width: 800%;
height: 100%;
fill: none;
stroke: currentColor;
stroke-width: 2.4;
stroke-linecap: round;
stroke-linejoin: round;
animation: kfa-sprite-sheet-steps-play 0.8s steps(8) infinite;
}
/* the ground moves at the speed of the planted foot */
.kfa-sprite-sheet-steps::after {
content: "";
position: absolute;
left: 0;
right: 0;
bottom: 0.18em;
height: 0.12em;
background: repeating-linear-gradient(90deg, rgb(255 255 255 / 0.55) 0 0.5em, transparent 0 0.96em);
animation: kfa-sprite-sheet-steps-ground 0.8s linear infinite;
}
@keyframes kfa-sprite-sheet-steps-play {
to { transform: translateX(-100%); }
}
@keyframes kfa-sprite-sheet-steps-ground {
to { background-position: -3.84em 0; }
}
@media (prefers-reduced-motion: reduce) {
.kfa-sprite-sheet-steps, .kfa-sprite-sheet-steps *, .kfa-sprite-sheet-steps::before, .kfa-sprite-sheet-steps::after, .kfa-sprite-sheet-steps *::before, .kfa-sprite-sheet-steps *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}--kfa-color on the element or a parent.
Currently previewing #3b82f6.--kfa-size. Every other dimension is in
em, so the whole thing scales together. Currently previewing 16px.transition or animation
shorthand. Staggered delays are relative, so they keep their rhythm.