Stop 14 · AnimationsTopics · 3/5

CSS Animation

Part of the Frontend Developer Roadmap

In short

Before reaching for a library, try plain CSS. Hover effects, loaders and fade-ins need zero JavaScript, add nothing to your bundle, and run smoothly on cheap phones.

Achieving motion using plain CSS `@keyframes`/`transition` rather than a JavaScript library — the lightest-weight option, ideal for simple, non-interactive animations.

The jaadu stands at a corner as a traffic light turns green, while another signal blinks yellow.

Think of it like this

Transition vs keyframes at the signal

A traffic light changing from red to green is a transition: one state to another when something happens. The blinking yellow at midnight is a keyframe animation: it loops on its own, no trigger needed.

Watch it happen

What the browser redoes each frame

Style
Layout
Paint
Composite

1/4Every animation frame starts with style: the browser works out the new value, like width 210px or translateY(-4px).

The big ideas

What you need to know

transition for state changes

Smoothly moves between two values when they change, like on :hover or when a class is added.

@keyframes for sequences

Define steps from 0% to 100% and run them with the animation property. They can loop forever.

Stick to transform and opacity

These skip layout and paint work, so they stay smooth. Animating width or margin makes the browser redo layout every frame.

Respect reduced motion

Some users get dizzy from motion. The prefers-reduced-motion media query lets you calm things down for them.

See it in code

Walk through the code

css
1.card { transition: transform 200ms ease, box-shadow 200ms ease; }2.card:hover { transform: translateY(-4px); box-shadow: 0 8px 20px rgb(0 0 0 / 0.15); }3 4@keyframes spin { to { transform: rotate(360deg); } }5.loader {6  width: 32px; height: 32px; border-radius: 50%;7  border: 3px solid #ddd; border-top-color: #7E39FE;8  animation: spin 0.8s linear infinite;9}10 11@media (prefers-reduced-motion: reduce) {12  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }13}

1/3A transition: when hover changes transform and box-shadow, they ease over 200ms.

The hover lift uses a transition, the loader uses keyframes. The last block makes motion near-instant for users who asked their OS to reduce motion.

Save yourself the pain

Common mistakes

Oops

Writing transition: all 0.3s on everything.

Do this instead

List the exact properties you animate. 'all' can animate things you didn't expect and costs more work.

Oops

Adding a JS animation library just for a button hover.

Do this instead

A CSS transition does it in one line with no extra bundle size.

Your mission

A no-JS loading screen

~20 min

Quick check

Which pair of properties is cheapest for the browser to animate?

Go deeper

  1. 1Recreate a simple Framer Motion animation using only CSS to compare effort and output.
  2. 2Learn which properties (`transform`, `opacity`) animate smoothly at 60fps.
  3. 3Know when plain CSS is enough and when you actually need a JS animation library.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge