← Back to the Animation Playground
Lesson

Animation, Visually

Motion guides attention, gives feedback, and makes an interface feel alive. This lesson covers CSS transitions and keyframe animations — transforms, easing, @keyframes, the common effects, and how to keep it all fast and accessible — with demos you can hover, run, and replay.

Step 1

Two tools: transitions & keyframes

CSS gives you two ways to move things, and picking the right one is half the battle:

ToolAnimatesBest for
transitionFrom state A → B when something changes (hover, a class toggle)Hovers, buttons, opening panels, micro-interactions.
@keyframes + animationA multi-step sequence that can loop on its ownSpinners, looping effects, attention-grabbers, entrances.
Simple rule: if motion happens in response to something (a hover, a click), use a transition. If it needs multiple steps or should run on its own (and maybe repeat), use a keyframe animation.
Step 2

Transitions: smooth A → B

A transition tells the browser to animate a change instead of snapping. You set it once; it fires whenever the value changes. Four parts: property, duration, timing function, optional delay.

.box {
  transition: transform .35s ease;   property duration easing
}
.box:hover { transform: scale(1.15); }   the change that gets animated
hover me — transform, background & border-radius all transition
Hover
List several properties at once: transition: transform .35s ease, background .35s ease; or animate everything with transition: all .3s ease (handy, but a touch less efficient than naming properties).
Step 3

What to animate (and what to avoid)

Not all properties are equal. Some are cheap for the browser to animate at 60fps; others force expensive recalculation of the whole layout and cause jank.

Animate these (fast)Avoid animating (slow)
transform (move, scale, rotate)width, height, top, left, margin
opacity (fades)box-shadow on big areas, filter in loops
The golden rule of smooth animation: move things with transform: translate() instead of left/top, and fade with opacity. These two are GPU-accelerated and don't trigger layout, so they stay buttery even on phones.
Step 4

transform: move, scale, rotate, skew

transform is the workhorse. It repositions an element visually without disturbing the layout around it. Click each to see it (with a springy easing):

box
transform: none
You can chain them: transform: translateY(-30px) rotate(20deg) scale(1.2) applies in order. Transforms also take a transform-origin (default the center) if you want to rotate/scale from a corner.
Step 5

Easing: the personality of motion

The timing function controls how speed changes over the duration. linear is robotic; real motion accelerates and decelerates. Hit Run — all four balls travel the same distance in the same time, but feel completely different:

linear
ease
ease-in-out
cubic-bezier (springy)
transition-timing-function: ease-in-out;
transition-timing-function: cubic-bezier(.34, 1.56, .64, 1);  overshoots = bouncy
ease (the default) suits most UI. ease-out feels responsive for things entering. A cubic-bezier that goes above 1 overshoots and springs back — that's the playful bounce.
Step 6

@keyframes: multi-step sequences

When you need more than a single A → B, define the steps with @keyframes — using from/to or percentages — then attach it with the animation property. Hit replay:

@keyframes dance {
  0%   { transform: translateY(0) rotate(0); }
  30%  { transform: translateY(-40px); }
  60%  { transform: rotate(180deg); border-radius: 50%; }
  100% { transform: rotate(360deg); }
}
.box { animation: dance 1.4s ease-in-out; }
Each percentage is a snapshot in time; the browser smoothly interpolates between them. 0% is the same as from, 100% the same as to.
Step 7

The animation properties

The animation shorthand bundles several controls. Know them individually — especially iteration, direction, and fill-mode:

PropertyControls
animation-nameWhich @keyframes to run.
animation-durationHow long one cycle takes (1.4s).
animation-timing-functionThe easing (same options as transitions).
animation-delayWait before starting.
animation-iteration-countHow many times — a number or infinite.
animation-directionnormal, reverse, or alternate (ping-pong).
animation-fill-modeforwards keeps the final frame after it ends.
animation: pulse 1.5s ease-in-out 0s infinite alternate;
/*         name  dur   easing      delay  count    direction */
infinite + alternate is the recipe for a smooth, endlessly breathing effect (like the pulse in the gallery below). Use forwards when an entrance animation should stay at its end state instead of snapping back.
Step 8

The effects you'll reach for

Most real-world animation is a handful of recognizable patterns. Here they are, all looping live:

spin (a rotate(360deg) loop) is your loading spinner. fade + slide together make the classic “fade-in-up” entrance. shake is great for signalling an invalid form field.
Step 9

Keep it fast & accessible

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}
Accessibility isn't optional here. Respecting prefers-reduced-motion is a one-block media query that prevents real harm (dizziness, nausea, migraines) for motion-sensitive users.
Step 10

Animation checklist

Where next

Keep going