Keyframes
Compose multi-stage keyframes, interpolation, stepped motion, and fill behavior.
Live preview
Defined points in an animation (0%, 50%, 100%) that the browser fills the gaps between.
Definition and close-term distinctions
English definitions are preserved verbatim from Animation Vocabulary; translations and distinctions help you choose precisely.
keyframesKeyframes
关键帧Defined points in an animation (0%, 50%, 100%) that the browser fills the gaps between.
动画中预先定义的节点(如 0%、50%、100%),浏览器会补全节点之间的画面。
interpolation-tweenInterpolation / Tween
插值 / 补间Generating all the in-between frames between a start and end value, so motion is continuous.
生成起始值与结束值之间的所有中间帧,让运动保持连续。
Interpolation / Tween generates frames between values; Keyframes defines state checkpoints on a timeline.
orchestrationOrchestration
动效编排Deliberately timing multiple animations so they feel like one coordinated motion.
有意识地安排多段动画的时间关系,让它们呈现为一个协调的整体动作。
Orchestration coordinates timing across multiple animations; Keyframes describes states inside one animation.
fill-modeFill mode
填充模式Whether an element keeps its first or last frame's styles before the animation starts or after it ends (e.g. forwards).
控制元素在动画开始前或结束后是否保留首帧或末帧样式,例如 forwards。
Fill mode controls which styles persist outside the active interval; Keyframes defines states inside it.
stepped-animationStepped animation
步进动画An animation that is divided into discrete steps, like a countdown timer.
被划分为若干离散步骤的动画,例如倒计时器。
Stepped animation jumps between discrete states; regular keyframes usually interpolate continuously between states.
Decide before this motion ships
Purpose, frequency, trigger, timing, interruptibility, and gesture rules shape the implementation.
Define multi-stage states, interpolation behavior, stepped rhythm, and post-animation styles.
Use for low-frequency motion with meaningful phases; simple feedback favors a single transition.
Trigger from an explicit state change or replay action, with each keyframe representing a meaningful phase.
Map the first frame to the pre-entry state and the last to the stable state; give exit its own shorter timeline.
On interruption, build the next timeline from current computed styles instead of snapping to a keyframe.
The timeline itself needs no gesture; interactive progress controls support pointer, touch, and keyboard.
Collapse to one state change and remove anticipation, overshoot, and repeated phases.
Copy into your interface
Current parameters update visual-state CSS, semantic HTML, the required vanilla JS runtime, and an interaction prompt.
.motion-demo.motion-demo--keyframes {
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: 12px;
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: 8px;
box-shadow: 0 1px 2px rgb(0 0 0 / 6%), 0 10px 28px rgb(0 0 0 / 7%);
}
.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: 7px;
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: 7px;
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: 8px; }
.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; }
}Pre-delivery review
- Review whether every phase improves understanding.
- Verify that fill-mode never leaves an unusable visual state.
Keep information accessible
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. |