Build multi-stop @keyframes animations with a real timeline, a visual cubic-bezier editor, and scrubbable playback.
Browse CSS lessonsClick a stop to edit it. Drag any stop (except the fixed 0% and 100% ends) to any position. "+" adds a new stop at the widest gap.
Only properties that actually change between stops end up in the generated CSS — leave a value the same everywhere and it’s left out entirely, not animated pointlessly.
Transform
Box shadow
How long one full pass through 0%–100% takes.
How long to wait, after the animation is applied, before it starts. During the delay the element shows its backwards fill state (or nothing, if fill-mode doesn’t include backwards).
How many times the animation repeats. Infinite is common for loops like a spinner; a finite count is common for a one-off entrance.
alternate reverses direction on every other pass (so it doesn’t snap back to 0% at the end of each loop) — reverse plays every pass backwards; normal never does.
What the element looks like outside the time the animation is actually running: forwards keeps the last keyframe’s values after it ends, backwards applies the first keyframe’s values during the delay, both does either, none reverts to the element’s own CSS.
Controls the speed curve within each pass — drag the two handles below, or pick a preset. The ball actually eases along the curve you set; it isn’t a static picture.
cubic-bezier(0.42, 0, 0.58, 1)
Applies to the selected layer, replacing its current stops — fully editable afterwards.
.box-1-1 {
animation: box-1-1 1500ms cubic-bezier(0.42, 0, 0.58, 1) 0ms infinite alternate none;
}
@keyframes box-1-1 {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(200px, 0px);
}
}