Skip to content
EzzyWeb

Level 3, Interactive Building, Chapter 13 of 24

CSS Transitions & Animations

Why this matters

Right now, when your JavaScript toggles a class to open a menu or show an error, the change happens instantly, snapping from one state to another. A little bit of motion, a menu that slides open, a button that gently grows on hover, an error message that fades in, makes an interface feel considered and responsive rather than abrupt. This isn't decoration for its own sake: well-used motion helps people understand what just changed and where their attention should go.

CSS gives you two complementary tools for this: transitions, which smoothly animate a property between two states, and keyframe animations, which describe a more elaborate sequence of steps. Both build directly on the classList toggling you learned in the events chapter, since a transition often just needs a class to be added or removed to kick in.

The lesson

Transitions: animating between two states

The transition property tells the browser to smoothly animate a change in a CSS property over time, rather than applying it instantly. You specify which property to animate, how long it should take, and optionally a timing function that shapes its speed curve, all directly in CSS. Crucially, transitions require two known states to interpolate between, they animate a property changing from one value to another, which is exactly what happens when JavaScript adds or removes a class that changes, say, an element's opacity or transform.

A simple hover transition
CSS
1.button {2  background: #2d6cdf;3  transform: scale(1);4  transition: transform 0.2s ease, background 0.2s ease;5}67.button:hover {8  transform: scale(1.05);9  background: #1f4fa8;10}
Both transform and background animate smoothly over 0.2 seconds instead of snapping instantly on hover.

Which properties to animate

Not every property is a good candidate for animation. transform (which covers scale, rotate, and translate) and opacity are the two properties browsers can animate most efficiently, since they don't force the browser to recalculate the page's layout on every frame. Animating properties like width, height, or margin works but can feel less smooth, especially on less powerful devices, because the browser has to recompute the positions of surrounding elements continuously. Where possible, prefer transform: translateX() over changing left or margin-left, and prefer transform: scale() over changing width and height directly.

Sliding a panel in with transform
CSS
1.panel {2  transform: translateX(-100%);3  transition: transform 0.3s ease-out;4}56.panel.open {7  transform: translateX(0);8}
Toggling the .open class with classList.toggle from JavaScript slides the panel smoothly into view.

Keyframe animations

Transitions only handle a move from one state to another, but sometimes you want a self-contained animation with several steps, like a spinner that rotates continuously or a notification that bounces briefly when it appears. The @keyframes rule lets you define named waypoints, using percentages from 0% to 100% (or the keywords from and to), each specifying property values at that point in the animation. You then apply that animation to an element with the animation property, which controls duration, timing, repeat count, and more, similar in spirit to how transition controls timing for a two-state change.

A pulsing loading indicator
CSS
1@keyframes pulse {2  0% { transform: scale(1); opacity: 1; }3  50% { transform: scale(1.15); opacity: 0.7; }4  100% { transform: scale(1); opacity: 1; }5}67.loading-dot {8  animation: pulse 1.2s ease-in-out infinite;9}
infinite makes the animation repeat forever, which suits an ongoing loading indicator rather than a one-time effect.

Timing functions and duration

Both transition and animation accept a duration and a timing function that shapes how speed changes over that duration. ease starts slow, speeds up, then slows down again, and is a comfortable default for most interface motion. linear moves at a constant speed, useful for continuous effects like a spinning loader, while ease-in and ease-out start or end slowly, useful for things entering or leaving the screen respectively. Durations for interface feedback are usually short, somewhere between 150 and 400 milliseconds; longer than that starts to feel sluggish rather than smooth, since the goal is to help someone track a change, not to put on a show.

  • transition animates a property smoothly between two known states, usually triggered by a class change or hover.
  • transform and opacity are the cheapest properties to animate; prefer them over width, height, or margin.
  • @keyframes defines a named, multi-step animation, applied to an element with the animation property.
  • Short durations (150-400ms) with an ease or ease-out timing function feel responsive rather than sluggish.

Pairing motion with JavaScript

In practice, JavaScript rarely animates anything directly, it just adds or removes classes at the right moments, exactly as you learned in the events chapter, and lets CSS handle the actual motion. This division keeps your JavaScript focused on logic, deciding when something should happen, while CSS stays focused on presentation, deciding what it looks like when it does. As you move into the Level 3 capstone, an interactive quiz app, you'll use this same pairing constantly: JavaScript will check answers and update state, while CSS transitions and animations will make correct and incorrect feedback, progress updates, and question changes feel smooth and satisfying rather than abrupt.

Try it yourself

Style a card that fades and slides into view when a 'visible' class is toggled on it, and add a button that toggles that class with JavaScript so you can see the transition run.

Live preview

Chapter boss project

Boss project: Animated Feedback Component (Capstone Kickoff)

Build a small feedback component: a button that, when clicked, reveals a message with a smooth fade-and-slide transition, and a separate 'success' message that briefly pulses using a keyframe animation to draw attention when it appears. This component is intentionally similar to the kind of feedback you'll need very soon in the Level 3 capstone, an Interactive Quiz App, where correct and incorrect answers need clear, pleasant visual feedback.

All of your motion should be defined in CSS, using transition for the two-state reveal and @keyframes plus the animation property for the pulse effect, while your JavaScript's only job is to add and remove classes at the right moments in response to a click.

Pay attention to which properties you animate, favor transform and opacity, and keep your durations short and purposeful rather than long and showy. When you're done, you'll have both the animation techniques and the JavaScript-plus-CSS pairing pattern you'll lean on throughout the capstone quiz app.

  • Start with the fade-and-slide transition alone, using opacity and transform, before adding the keyframe pulse on top.
  • Define the pulse as its own @keyframes rule and apply it with animation only on the success message, not the whole component.
  • Use classList.add rather than toggle if you want the reveal to only ever go one direction once triggered.
  • If an animation feels sluggish, shorten the duration first before changing anything else.

Level-up checklist

Tick these off once each one is true for you.