keyframesKeyframes
Compose multi-stage keyframes, interpolation, stepped motion, and fill behavior.
Preview
Named timeline checkpoints assign property values at selected offsets; interpolation determines the states between them.
Implement Keyframes: Compose multi-stage keyframes, interpolation, stepped motion, and fill behavior. Use Demo duration 720ms, Timeline mode keyframes, Steps 4, Fill mode both, Easing soft. Trigger it once when state changes and keep it replayable. Use semantic HTML, scope CSS to .motion-demo--keyframes. Provide equivalent low-motion behavior for prefers-reduced-motion and .force-reduced-motion.
<div class="motion-demo motion-demo--keyframes" data-motion="keyframes" aria-label="Keyframes demo">
<article class="motion-surface">
<strong>Keyframes</strong>
<span class="motion-line"></span>
<span class="motion-line"></span>
</article>
</div>.motion-demo.motion-demo--keyframes {
box-sizing: border-box;
position: relative;
display: grid;
place-items: center;
width: min(100%, 34rem);
min-height: 15rem;
padding: 2rem;
overflow: hidden;
color: #18181b;
background: #fafafa;
border: 1px solid #e4e4e7;
border-radius: 16px;
isolation: isolate;
}
.motion-demo.motion-demo--keyframes *, .motion-demo.motion-demo--keyframes *::before, .motion-demo.motion-demo--keyframes *::after {
box-sizing: border-box;
}
.motion-demo.motion-demo--keyframes .motion-surface {
position: relative;
display: grid;
gap: 0.65rem;
width: min(100%, 18rem);
padding: 1.25rem;
background: #ffffff;
border: 1px solid #e4e4e7;
border-radius: 16px;
box-shadow: none;
}
.motion-demo.motion-demo--keyframes .motion-surface strong { font-weight: 500; }
.motion-demo.motion-demo--keyframes .motion-line {
display: block;
width: 100%;
height: 0.5rem;
background: #e4e4e7;
border-radius: 999px;
}
.motion-demo.motion-demo--keyframes .motion-line:last-child { width: 62%; }
.motion-demo.motion-demo--keyframes .motion-button {
position: relative;
min-height: 2.75rem;
padding: 0.75rem 1.1rem;
color: white;
font: inherit;
font-weight: 700;
background: #18181b;
border: 0;
border-radius: 999px;
cursor: pointer;
}
.motion-demo.motion-demo--keyframes .motion-button:focus-visible { outline: 3px solid rgb(37 99 235 / 32%); outline-offset: 3px; }
.motion-demo.motion-demo--keyframes .motion-action-row {
display: flex;
justify-content: center;
gap: 0.5rem;
margin-top: 0.85rem;
}
.motion-demo.motion-demo--keyframes .motion-replay-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--keyframes .motion-pausable-scene {
width: min(100%, 22rem);
display: grid;
place-items: center;
}
.motion-demo.motion-demo--keyframes button.motion-surface {
color: inherit;
font: inherit;
text-align: start;
cursor: pointer;
}
.motion-demo.motion-demo--keyframes .motion-replay-button,
.motion-demo.motion-demo--keyframes .motion-undo-button,
.motion-demo.motion-demo--keyframes .motion-dismiss-button,
.motion-demo.motion-demo--keyframes .motion-pause-button {
min-height: 2.75rem;
padding: 0.65rem 0.9rem;
color: #18181b;
font: 650 0.78rem/1 ui-sans-serif, system-ui, sans-serif;
background: #ffffff;
border: 1px solid #d4d4d8;
border-radius: 8px;
cursor: pointer;
}
.motion-demo.motion-demo--keyframes .motion-replay-button:focus-visible,
.motion-demo.motion-demo--keyframes .motion-undo-button:focus-visible,
.motion-demo.motion-demo--keyframes .motion-dismiss-button:focus-visible,
.motion-demo.motion-demo--keyframes .motion-pause-button:focus-visible,
.motion-demo.motion-demo--keyframes [data-reorder-item]:focus-visible,
.motion-demo.motion-demo--keyframes [data-swipe-target]:focus-visible {
outline: 3px solid rgb(37 99 235 / 32%);
outline-offset: 3px;
}
.motion-demo.motion-demo--keyframes .motion-status {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.motion-demo.motion-demo--keyframes .motion-ripple-ink {
position: absolute;
width: 12px;
height: 12px;
pointer-events: none;
background: rgb(255 255 255 / 72%);
border-radius: 50%;
transform: translate(-50%, -50%) scale(0.95);
opacity: 0;
}
.motion-demo.motion-demo--keyframes .motion-state-stack { position: relative; width: min(100%, 18rem); height: 9rem; }
.motion-demo.motion-demo--keyframes .motion-state { position: absolute; inset: 0; display: grid; place-items: center; padding: 1rem; background: #ffffff; border: 1px solid #e4e4e7; border-radius: 16px; }
.motion-demo.motion-demo--keyframes .motion-state--to { background: #18181b; color: white; }
.motion-demo.motion-demo--keyframes .motion-scroll-track > span { color: #71717a; font: 600 0.72rem/1.2 ui-monospace, monospace; letter-spacing: 0.08em; text-transform: uppercase; }
.motion-demo.motion-demo--keyframes .motion-orbit-item { display: grid; place-items: center; width: 2.5rem; height: 2.5rem; color: white; background: #2563eb; border-radius: 50%; }
.motion-demo.motion-demo--keyframes .motion-text-stack { position: relative; width: min(100%, 18rem); min-height: 4rem; }
.motion-demo.motion-demo--keyframes svg { width: min(100%, 20rem); height: auto; }
.motion-demo.motion-demo--keyframes .motion-surface { animation: motion-keyframes 720ms cubic-bezier(0.23, 1, 0.32, 1) 0ms 1 both; }
@keyframes motion-keyframes { 0% { opacity: 0.45; transform: translateX(-46px); } 50% { transform: translateX(46px) rotate(4deg); } 100% { opacity: 1; transform: translateX(46px); } }
@keyframes motion-keyframes-reduced-fade {
from { opacity: 0.84; }
to { opacity: 1; }
}
.force-reduced-motion .motion-demo.motion-demo--keyframes {
animation: motion-keyframes-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.force-reduced-motion .motion-demo.motion-demo--keyframes *,
.force-reduced-motion .motion-demo.motion-demo--keyframes *::before,
.force-reduced-motion .motion-demo.motion-demo--keyframes *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.force-reduced-motion .motion-demo.motion-demo--keyframes .motion-button,
.force-reduced-motion .motion-demo.motion-demo--keyframes [data-reorder-item],
.force-reduced-motion .motion-demo.motion-demo--keyframes [data-swipe-target],
.force-reduced-motion .motion-demo.motion-demo--keyframes [data-spring-target] {
transform: none !important;
}
.force-reduced-motion .motion-demo.motion-demo--keyframes .motion-path { stroke-dashoffset: 0 !important; }
.force-reduced-motion .motion-demo.motion-demo--keyframes .motion-word--from { opacity: 0 !important; visibility: hidden; }
.force-reduced-motion .motion-demo.motion-demo--keyframes .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
@media (prefers-reduced-motion: reduce) {
.motion-demo.motion-demo--keyframes {
animation: motion-keyframes-reduced-fade 160ms cubic-bezier(0.23, 1, 0.32, 1) both !important;
}
.motion-demo.motion-demo--keyframes *, .motion-demo.motion-demo--keyframes *::before, .motion-demo.motion-demo--keyframes *::after {
animation: none !important;
animation-delay: 0ms !important;
animation-iteration-count: 1 !important;
transition-property: opacity, color, background-color, border-color !important;
transition-duration: 160ms !important;
transition-delay: 0ms !important;
scroll-behavior: auto !important;
}
.motion-demo.motion-demo--keyframes .motion-button,
.motion-demo.motion-demo--keyframes [data-reorder-item],
.motion-demo.motion-demo--keyframes [data-swipe-target],
.motion-demo.motion-demo--keyframes [data-spring-target] {
transform: none !important;
}
.motion-demo.motion-demo--keyframes .motion-path { stroke-dashoffset: 0 !important; }
.motion-demo.motion-demo--keyframes .motion-word--from { opacity: 0 !important; visibility: hidden; }
.motion-demo.motion-demo--keyframes .motion-word:not(.motion-word--from) { opacity: 1 !important; filter: none !important; transform: none !important; }
}Learn more
Terms and distinctions
keyframesKeyframes
关键帧Named timeline checkpoints assign property values at selected offsets; interpolation determines the states between them.
动画中预先定义的节点(如 0%、50%、100%),浏览器会补全节点之间的画面。
interpolation-tweenInterpolation / Tween
插值 / 补间A renderer calculates intermediate property values between defined states to produce continuous change.
生成起始值与结束值之间的所有中间帧,让运动保持连续。
Interpolation / Tween generates frames between values; Keyframes defines state checkpoints on a timeline.
orchestrationOrchestration
动效编排A coordinated timeline orders multiple motions so their starts, overlaps, and finishes express one event.
有意识地安排多段动画的时间关系,让它们呈现为一个协调的整体动作。
Orchestration coordinates timing across multiple animations; Keyframes describes states inside one animation.
fill-modeFill mode
填充模式A fill mode selects which keyframe styles apply outside the active animation interval.
控制元素在动画开始前或结束后是否保留首帧或末帧样式,例如 forwards。
Fill mode controls which styles persist outside the active interval; Keyframes defines states inside it.
stepped-animationStepped animation
步进动画Progress advances through fixed discrete states instead of continuously interpolated values.
被划分为若干离散步骤的动画,例如倒计时器。
Stepped animation jumps between discrete states; regular keyframes usually interpolate continuously between states.
Before implementation
- Purpose
- Define multi-stage states, interpolation behavior, stepped rhythm, and post-animation styles.
- Frequency
- Use for low-frequency motion with meaningful phases; simple feedback favors a single transition.
- Trigger
- Trigger from an explicit state change or replay action, with each keyframe representing a meaningful phase.
- Enter / exit
- Map the first frame to the pre-entry state and the last to the stable state; give exit its own shorter timeline.
- Interruptibility
- On interruption, build the next timeline from current computed styles instead of snapping to a keyframe.
- Gesture and keyboard
- The timeline itself needs no gesture; interactive progress controls support pointer, touch, and keyboard.
- Reduced-motion strategy
- Collapse to one state change and remove anticipation, overshoot, and repeated phases.
Accessibility
Collapse to one state change and remove anticipation, overshoot, and repeated phases.
Parameter reference
| Parameter | Range / options | Default | Purpose |
|---|---|---|---|
duration | 300ms–2400ms | 720ms | Uses a longer demo duration so the full change stays observable; immediate production UI feedback should stay under 300ms. |
mode | Keyframes / Tween / Steps | Keyframes | Selects timeline mode. |
steps | 2–12 | 4 | Adjusts steps. |
fill | None / Forwards / Both | Both | Selects fill mode. |
ease | Soft / Snap / Calm / Linear | Soft | Controls how velocity changes over time. |
Pre-delivery review
- Review whether every phase improves understanding.
- Verify that fill-mode never leaves an unusable visual state.