The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Choose transitioned properties | .button {
transition-property: background-color, transform;
} | View examples |
| Set transition duration | .button { transition-duration: 160ms; } | View examples |
| Declare a transition | .button { transition: transform 160ms ease-out; } | View examples |
| Transition several properties | .card {
transition:
transform 180ms ease-out, box-shadow 180ms ease-out;
} | View examples |
| Delay a transition | .item { transition-delay: 80ms; } | View examples |
| Use custom easing | .panel {
transition-timing-function:
cubic-bezier(.2, .8, .2, 1);
} | View examples |
| Use stepped timing | .sprite { transition-timing-function: steps(6, end); } | View examples |
| Define keyframes | @keyframes fade-in {
from { opacity: 0; } to { opacity: 1; };
} | View examples |
| Run a keyframe animation | .notice { animation: fade-in 240ms ease-out; } | View examples |
| Add intermediate keyframes | @keyframes pulse {
0%, 100% { opacity: 1; } 50% { opacity: .55; };
} | View examples |
| Repeat an animation | .spinner { animation-iteration-count: infinite; } | View examples |
| Alternate direction | .indicator { animation-direction: alternate; } | View examples |
| Retain the final keyframe | .enter { animation-fill-mode: forwards; } | View examples |
| Pause an animation | .carousel:hover { animation-play-state: paused; } | View examples |
| Move with transform | .card:hover { transform: translateY(-.25rem); } | View examples |
| Fade with opacity | .popover[data-open="true"] { opacity: 1; } | View examples |
| Honor reduced motion | @media (prefers-reduced-motion: reduce) {
.animated { animation:
none; transition-duration: .01ms; };
} | View examples |
| Preserve a clear focus state | .button:focus-visible {
outline: .2rem solid currentColor;
outline-offset: .2rem;
} | View examples |
Use transitions when a property changes between states and keyframe animations when motion needs its own timeline. Animate only properties that clarify feedback or relationships, keep controls usable when motion is absent, and provide a reduced-motion path for nonessential effects.
Step by step
Detailed examples
Transition explicit state changes
A transition begins when an element's computed value changes and the old and new values are transitionable. Name the properties rather than using all, which can animate future changes unintentionally. The first time value is duration and the optional second time is delay; comma-separated lists pair definitions by position.
.button {
background: #2563eb;
transform: translateY(0);
transition: background-color 160ms ease-out,
transform 160ms ease-out;
}
.button:hover {
background: #1d4ed8;
transform: translateY(-.125rem);
} Match easing and delay to the interaction
Timing functions map elapsed time to progress. ease-out often suits elements entering or reacting because it starts quickly and settles; linear suits mechanically constant progress; steps is useful for frame-like changes. Long delays can make interfaces feel broken, and staggered delays should not postpone access to important information.
.panel {
transition: transform 220ms cubic-bezier(.2, .8, .2, 1) 40ms;
}
.sprite {
transition: background-position 600ms steps(6, end);
} Define a timeline with keyframes
@keyframes creates a named set of offsets; from and to equal 0% and 100%. Properties omitted at an offset are interpolated from the element's underlying style or neighboring keyframes where possible. Applying animation-name alone has no visible duration because the initial duration is zero, so set timing explicitly.
@keyframes enter {
from { opacity: 0; transform: translateY(.5rem); }
70% { opacity: 1; transform: translateY(-.0625rem); }
to { opacity: 1; transform: translateY(0); }
}
.notice { animation: enter 240ms ease-out; } Control repetition, direction, and applied endpoints
iteration-count controls repetitions and may be fractional; infinite motion should be reserved for genuine ongoing activity. alternate avoids a discontinuous jump between end and start. fill-mode changes which keyframe styles apply outside the active interval, but forwards is not a substitute for setting the element's durable end state in application logic.
@keyframes breathe {
from { opacity: .45; transform: scale(.96); }
to { opacity: 1; transform: scale(1); }
}
.indicator {
animation: breathe 900ms ease-in-out infinite alternate;
} Expose a way to pause persistent motion
animation-play-state pauses or resumes without resetting elapsed progress. Pause controls are preferable to hover-only pausing because hover is unavailable to many users and devices. If motion begins automatically and lasts more than a brief period, provide an operable control and persist the user's choice where appropriate.
<div class="banner animated" data-paused="false">System status</div>
<button type="button" id="motion-toggle">Pause animation</button>
<script>
const banner = document.querySelector('.banner');
const button = document.querySelector('#motion-toggle');
button.addEventListener('click', () => {
const paused = banner.dataset.paused !== 'true';
banner.dataset.paused = String(paused);
button.textContent = paused ? 'Resume animation' : 'Pause animation';
});
</script>
<style>
.animated { animation: breathe 900ms ease-in-out infinite alternate; }
.animated[data-paused="true"] { animation-play-state: paused; }
</style> Prefer motion that does not relayout surrounding content
transform and opacity can often be composited efficiently and do not alter the document's layout geometry. Animating dimensions or positional layout properties may trigger repeated layout and paint work and can move neighboring content. Performance still depends on element size, effects, and device, so profile real pages rather than treating any property as free.
.popover {
opacity: 0;
transform: translateY(-.25rem);
pointer-events: none;
transition: opacity 140ms ease-out, transform 140ms ease-out;
}
.popover[data-open="true"] {
opacity: 1;
transform: translateY(0);
pointer-events: auto;
}
.card { transition: transform 180ms ease-out; }
.card:hover { transform: translateY(-.25rem); } Keep meaning and focus independent from motion
prefers-reduced-motion:reduce indicates a request to minimize nonessential movement. Replace large travel, parallax, pulsing, and automatic loops with immediate or subtle state changes while preserving essential progress feedback. Never use animation alone to communicate focus, validation, or completion; retain text, color-independent markers, and visible focus outlines.
.animated { animation: enter 240ms ease-out; }
.button { transition: transform 160ms ease-out; }
.button:focus-visible {
outline: .2rem solid currentColor;
outline-offset: .2rem;
}
@media (prefers-reduced-motion: reduce) {
.animated { animation: none; }
.button { transition-duration: .01ms; }
} Local code tester
Try CSS transitions and animations
Change transition timing, keyframes, pause state, and reduced-motion overrides in a local preview.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



