Motion

animation-duration

Setting the length of time that an animation takes to complete one cycle.

Overview

ClassDeclarations
animation-duration-fastestanimation-duration: var(--duration-fastest);
animation-duration-fasteranimation-duration: var(--duration-faster);
animation-duration-fastanimation-duration: var(--duration-fast);
animation-duration-normalanimation-duration: var(--duration-normal);
animation-duration-slowanimation-duration: var(--duration-slow);
animation-duration-sloweranimation-duration: var(--duration-slower);
animation-duration-slowestanimation-duration: var(--duration-slowest);
animation-duration:<duration>,<…>animation-duration: <duration>,<…>;

Examples

Set animation speed

Compare the same 72px path over 500ms and one second. Duration controls one cycle, independently of delay and repetition.

Set animation speed
animation-duration: Set animation speed controls
Play opts into the actual CSS animation. Pause retains its time; Replay restarts even a finished one-shot. Readouts show native timeline time and progress, including delay and fill.
index.css
@theme {  @keyframes layer-slide {    from { transform: translateX(24px); }    to { transform: translateX(96px); }  }}
<!-- 500ms cycle --><div class="w:240px max-w:100%">  <p class="mb-sm font-mono font-xs text-muted">Base 0 · start 24 · end 96px</p>  <div aria-hidden="true"    class="h:56px p-xs outline:1px|dashed|var(--color-line-muted)">    <span id="target"      class="grid place-items:center h:40px w:48px             b:1px|solid|var(--color-blue-60) r-sm bg-blue-10             fg-blue-80 transform:none             animation-duration-slower             animation-fill-mode:forwards             animation-name:layer-slide             animation-timing-function:linear             animation:none@print             animation-play-state:paused@reduce-motion">→</span>  </div></div>
<!-- One-second cycle --><div class="w:240px max-w:100%">  <p class="mb-sm font-mono font-xs text-muted">Base 0 · start 24 · end 96px</p>  <div aria-hidden="true"    class="h:56px p-xs outline:1px|dashed|var(--color-line-muted)">    <span id="target"      class="grid place-items:center h:40px w:48px             b:1px|solid|var(--color-blue-60) r-sm bg-blue-10             fg-blue-80 transform:none             animation-duration:1s             animation-fill-mode:forwards             animation-name:layer-slide             animation-timing-function:linear             animation:none@print             animation-play-state:paused@reduce-motion">→</span>  </div></div>
Generated CSS
@layer theme {  :root,  :host {    --duration-slower: .5s  }}@layer utilities {  .animation-duration-slower {    animation-duration: var(--duration-slower)  }}

Use a duration token or a nonnegative CSS time. At 250ms the first marker is halfway through its cycle; the second is one quarter through.

Slow down looping motion

Compare one-second and three-second rotations with the same linear timing and infinite count.

Slow down looping motion
animation-duration: Slow down looping motion controls
Play opts into the actual CSS animation. Pause retains its time; Replay restarts even a finished one-shot. Readouts show native timeline time and progress, including delay and fill.
<!-- One-second loop --><div class="flex items-center gap-md p-sm">  <svg id="target" aria-hidden="true" width="48" height="48" viewBox="0 0 48 48"    fill="none" stroke="currentColor" stroke-width="2"    class="text-blue animation-duration:1s           animation-iteration-count:infinite           animation-name:rotate           animation-timing-function:linear           animation:none@print           animation-play-state:paused@reduce-motion">    <circle cx="24" cy="24" r="17" opacity=".25" />    <path d="M24 8v16h12 M19 13l5-5 5 5" />  </svg>  <span class="font-sm">One-second loop</span></div>
<!-- Three-second loop --><div class="flex items-center gap-md p-sm">  <svg id="target" aria-hidden="true" width="48" height="48" viewBox="0 0 48 48"    fill="none" stroke="currentColor" stroke-width="2"    class="text-blue animation-duration:3s           animation-iteration-count:infinite           animation-name:rotate           animation-timing-function:linear           animation:none@print           animation-play-state:paused@reduce-motion">    <circle cx="24" cy="24" r="17" opacity=".25" />    <path d="M24 8v16h12 M19 13l5-5 5 5" />  </svg>  <span class="font-sm">Three-second loop</span></div>

Longer duration lowers the steady angular speed. Keep progress text separate from decoration and provide a way to pause continuous motion.

Remove animation in static output

Compare a one-second animation with zero duration. Both use forwards fill; the zero-duration specimen immediately retains the ending keyframe.

Remove animation in static output
animation-duration: Remove animation in static output controls
Play opts into the actual CSS animation. Pause retains its time; Replay restarts even a finished one-shot. Readouts show native timeline time and progress, including delay and fill.
index.css
@theme {  @keyframes layer-slide {    from { transform: translateX(24px); }    to { transform: translateX(96px); }  }}
<!-- One second · retains end --><div class="w:240px max-w:100%">  <p class="mb-sm font-mono font-xs text-muted">Base 0 · start 24 · end 96px</p>  <div aria-hidden="true"    class="h:56px p-xs outline:1px|dashed|var(--color-line-muted)">    <span id="target"      class="grid place-items:center h:40px w:48px             b:1px|solid|var(--color-blue-60) r-sm bg-blue-10             fg-blue-80 transform:none             animation-duration:1s             animation-fill-mode:forwards             animation-name:layer-slide             animation-timing-function:linear             animation:none@print             animation-play-state:paused@reduce-motion">→</span>  </div></div>
<!-- Zero duration · immediate end --><div class="w:240px max-w:100%">  <p class="mb-sm font-mono font-xs text-muted">Base 0 · start 24 · end 96px</p>  <div aria-hidden="true"    class="h:56px p-xs outline:1px|dashed|var(--color-line-muted)">    <span id="target"      class="grid place-items:center h:40px w:48px             b:1px|solid|var(--color-blue-60) r-sm bg-blue-10             fg-blue-80 transform:none             animation-duration:0ms             animation-fill-mode:forwards             animation-name:layer-slide             animation-timing-function:linear             animation:none@print             animation-play-state:paused@reduce-motion">→</span>  </div></div>

Zero duration is not the same as animation:none: fill can still apply a keyframe and start/end events can still occur. These snippets remove the animation in print, which restores the ordinary 0px position.

Apply conditionally

Resize before replaying to switch from a 500ms cycle to one second at sm. The path and linear easing stay fixed.

Apply conditionally
animation-duration: Apply conditionally controls
Play opts into the actual CSS animation. Pause retains its time; Replay restarts even a finished one-shot. Readouts show native timeline time and progress, including delay and fill.
index.css
@theme {  @keyframes layer-slide {    from { transform: translateX(24px); }    to { transform: translateX(96px); }  }}
<!-- 500ms → one second at sm --><div class="w:240px max-w:100%">  <p class="mb-sm font-mono font-xs text-muted">Base 0 · start 24 · end 96px</p>  <div aria-hidden="true"    class="h:56px p-xs outline:1px|dashed|var(--color-line-muted)">    <span id="target"      class="grid place-items:center h:40px w:48px             b:1px|solid|var(--color-blue-60) r-sm bg-blue-10             fg-blue-80 transform:none             animation-duration-slower             animation-fill-mode:forwards             animation-name:layer-slide             animation-timing-function:linear             animation:none@print             animation-play-state:paused@reduce-motion             animation-duration:1s@sm">→</span>  </div></div>

Changing duration can update the phase of an existing animation. Replay makes the selected cycle length easy to compare from its start.



© 2026 Aoyue Design LLC.MIT License
Trademark Policy