animation-duration sets how long one animation cycle takes. Repeating an animation multiplies its active time; delay is separate.
Compare half a second with two seconds
Check the control to start both squares together. Each moves the same distance once, but the second takes four times as long.
HTML and CSS
HTML
<input class="run" id="run" type="checkbox" /><label for="run"
>Run the demonstration; uncheck to reset</label
>
<div class="stage">
<p>.5s</p>
<div class="box" aria-hidden="true"></div>
<p>2s</p>
<div class="box slow" aria-hidden="true"></div>
</div>
CSS
@keyframes travel {
from {
transform: translateX(0);
}
to {
transform: translateX(100px);
}
}
.stage {
background: #eff6ff;
padding: 1rem;
}
.box {
width: 50px;
height: 35px;
background: #2563eb;
margin-block: 0.5rem;
}
label {
display: inline-block;
padding: 0.75rem;
}
.run:checked ~ .stage .box {
animation-name: travel;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-duration: 0.5s;
}
.run:checked ~ .stage .slow {
animation-duration: 2s;
}
@media (prefers-reduced-motion: reduce) {
.run:checked ~ .stage .box {
animation-name: none;
}
}
Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.
Inspect a zero-duration final state
Duration 0s gives no interpolated motion. Forwards fill still applies the final keyframe, so checking the control places the square immediately at the end.
HTML and CSS
HTML
<input class="run" id="run" type="checkbox" /><label for="run"
>Run the demonstration; uncheck to reset</label
>
<div class="stage"><div class="box" aria-hidden="true"></div></div>
CSS
@keyframes travel {
from {
transform: translateX(0);
}
to {
transform: translateX(100px);
}
}
.stage {
background: #eff6ff;
padding: 1rem;
}
.box {
width: 50px;
height: 35px;
background: #2563eb;
margin-block: 0.5rem;
}
label {
display: inline-block;
padding: 0.75rem;
}
.run:checked ~ .stage .box {
animation-name: travel;
animation-duration: 0s;
animation-fill-mode: forwards;
}
@media (prefers-reduced-motion: reduce) {
.run:checked ~ .stage .box {
animation-name: none;
}
}
Edit HTML or CSS to update the preview as you type. Copy code snippet copies the selected tab. Preview spacing and font defaults are not included.
Values and defaults
For established time-based animations the initial duration is 0s, and the property is not inherited. Explicit times must be nonnegative with s/ms units; negative durations are invalid. Modern auto is equivalent to 0s for a time-based animation and fills the timeline for a scroll-driven animation, with separate value support considerations.
Common mistakes
Zero does not mean the animation cannot execute: events and fill behavior can still apply. Two iterations of a one-second animation take two active seconds, not one. A missing keyframe name cannot be repaired by setting duration. Comma-separated durations map to animation-name order; a later shorthand resets them.
The old spinner comparison concealed one duration behind a utility and had uncontrolled looping. These examples run on request and preserve a stationary fallback for reduced motion. Learn animation-delay, animation-iteration-count, and animation-fill-mode.
The demonstrations are stationary when prefers-reduced-motion:reduce is active. Their code remains available for inspection.
Sources and browser support
MDN: animation-duration describes the syntax and links to the specification and compatibility data. Check individual values in that table when supporting older browsers.