Site icon Ampersand Tutorials

CSS Transitions and Animations Guide (2026)

Quick answer: CSS animations run a @keyframes sequence on their own, with multiple steps, loops and direction, while a transition animates a property only when its value changes, usually on hover or focus. Animate transform and opacity for smooth performance, keep durations short, and always respect prefers-reduced-motion.

Transitions: from one value to another

A transition needs four things: a start value, an end value triggered by a state, the property to animate, and a duration.

.button {
  background: #0f766e;
  transform: translateY(0);
  transition: background-color 200ms ease, transform 200ms ease;
}
.button:hover {
  background: #115e59;
  transform: translateY(-2px);
}

Writing CSS animations with @keyframes

When you need more than a start and end, or the animation should run without a user action, use @keyframes.

@keyframes fade-up {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

.alert {
  animation: fade-up 300ms ease-out both;
}

.spinner {
  animation: spin 1s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

The animation shorthand takes name, duration, timing, delay, iteration count and fill mode. The both fill mode is useful: it applies the first keyframe’s values before the animation starts and keeps the last after it ends, so there is no flash of unstyled content.

PropertyPurpose
animation-iteration-count1 or infinite
animation-directionnormal, reverse, alternate
animation-play-statepaused to stop on interaction
animation-fill-modeboth to hold start and end values

Animate the cheap properties in CSS animations

Performance depends on which properties you animate. transform and opacity are handled by the compositor and do not trigger layout, so they stay smooth even on busy pages. Animating width, height, top or margin forces the browser to recalculate layout on every frame.

/* avoid: triggers layout each frame */
.panel { transition: width 300ms; }

/* prefer: composite-only, no layout */
.panel { transition: transform 300ms; }
.panel.open { transform: scaleX(1); }

Where you need a size change, animating transform: scale() is usually the fast substitute. Check the DevTools Performance panel if a card of yours stutters — it shows exactly which frames triggered layout.

Motion accessibility is not optional

Some people are made ill by large or looping motion. Respect the operating-system setting with one media query that turns animation off for those who ask.

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

That block keeps the interface functional while removing the motion. Add it to every project, and test it in your browser’s emulation settings before shipping.

View transitions and CSS animations, briefly

For richer page or state changes, the View Transitions API animates between two DOM states with a single call to document.startViewTransition() and a little CSS. It is a newer capability — widely available for same-document transitions, with less complete support for cross-document ones — so use it as progressive enhancement. When you want a simple hover or entrance, transitions and keyframes above remain the everyday tools.

That completes the CSS series. To learn modern CSS with a mentor on real designs, Ampersand Academy teaches web development one-to-one.

Frequently asked questions

What is the difference between a transition and an animation?

A transition animates a property between two values when a state changes, such as hover. An animation runs a keyframe sequence with multiple steps and can loop without any user action.

Which CSS properties are cheapest to animate?

Transform and opacity, because the compositor handles them without recalculating layout. Animating width, height or margin forces layout on every frame and can stutter.

How long should a CSS transition be?

For interface feedback, 150 to 300 milliseconds. Shorter feels instant, longer feels sluggish. Reserve durations over 500ms for large or cinematic movement.

How do I respect prefers-reduced-motion?

Add a media query for prefers-reduced-motion reduce that sets animation and transition durations to nearly zero. It keeps the interface working while removing uncomfortable motion.

What does animation-fill-mode both do?

It applies the first keyframe before the animation starts and holds the last keyframe after it ends, preventing a flash of unstyled or reset content.

Exit mobile version