Design

CSS Transition Basics: Properties, Hover Animations, and Smooth Motion

A CSS transition smoothly bridges the "change" that happens when an element shifts state. This article explains the four parts that make up a transition, how to change color and size on hover, the difference from animation, easing (timing-function) tips for natural motion, and the performance pitfalls to watch for.

Published: 2026-10-16

Have you seen websites where a button softly changes color when you hover over it, or a menu slides smoothly open? You can achieve this "smooth motion when state changes" in just a few lines with a CSS transition. This article walks you through what a transition is, its four parts, changing color and size on hover, the difference from animation, easing tips for natural motion, and the performance pitfalls to watch for.

What a CSS Transition Is

A transition is a mechanism that, when a CSS property value changes, does not switch it instantly but interpolates the change smoothly over a time you specify. For example, when you change a background from white to blue, without a transition it switches in an instant, but with a transition it gradually shifts from white to blue.

A transition fires the moment an element's state changes. Common triggers are :hover when the mouse moves over an element, :focus on click or focus, and toggling a class with JavaScript. The essence of a transition is that once you set "the before and after values" and "how long it takes," the browser computes the in-between frames automatically. You do not need to write each intermediate state by hand.

To quickly test how motion feels, it is easy to preview hover changes in the Button Generator. Before writing any code, you can see with your own eyes which motion feels pleasant.

The Four Parts of a Transition

A transition is built from the following four properties. Using the shorthand transition lets you write them all at once.

PropertyRoleExample
transition-propertyWhich CSS property to changebackground-color
transition-durationHow long the change takes0.3s
transition-timing-functionThe pacing of the change (easing)ease
transition-delayThe wait before the change starts0s

transition-property specifies the target property. Setting all targets every property that changes, but from the performance angle discussed later, it is best to name the property you want to change explicitly.

transition-duration is the time the change takes, given in seconds (s) or milliseconds (ms). Omit it and it becomes 0s, so the transition effectively does nothing. Remember: if you want motion, you must specify a time.

With the shorthand, you can combine everything in one line:

transition: background-color 0.3s ease 0s;

This means "change background-color over 0.3 seconds, with ease pacing, after a 0-second delay." To move several properties at once, separate them with commas, like transition: color 0.2s, transform 0.3s;.

Changing Color and Size on Hover

The most familiar use of a transition is the hover change. The key point is to write the transition on the "normal state" side. That way, the change is smooth in both directions, both entering and leaving the hover.

.btn {
  background-color: #3b82f6;
  transition: background-color 0.3s ease;
}
.btn:hover {
  background-color: #2563eb;
}

In this example, the button background smoothly shifts to a slightly darker blue on hover. To change size, the standard approach is transform: scale().

.card {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
  transform: scale(1.05);
  box-shadow: 0 8px 24px rgba(0,0,0,0.15);
}

The trick when changing size is to use transform: scale() rather than width or height. The performance chapter covers why in detail, but in short, transform avoids recomputing layout and is easy to animate smoothly. Combining color, size, and shadow creates a pleasant hover with a sense of depth. When experimenting with such combinations, it is efficient to change each property and check the result in the Button Generator.

Transition vs. Animation

Besides transition, CSS offers animation (with @keyframes) for adding motion. They are similar, but their strengths clearly differ.

TransitionAnimation
TriggerNeeds a state change (such as hover)Can start automatically, e.g. on load
Stages of motionBetween a start and an end pointMultiple keyframes possible
RepetitionNot possible (one shot each)Infinite loops or a set count possible
Best forUI state changesLoading and decorative motion

Transition excels at smoothly bridging a two-point change "from one state to another" in response to a trigger. UI motion that reacts to hover, focus, or class toggling is almost always handled well by a transition alone.

Animation, on the other hand, lets you specify any number of intermediate states with @keyframes, play automatically on page load, or repeat infinitely. A spinning loading indicator or decoration that blinks or moves on its own cannot be made with a transition, so animation steps in. It is easy to choose if you remember: transition for "simple changes that react to user action," animation for "automatic, repeating, or multi-stage motion."

Easing Tips for Natural Motion

What greatly shapes the impression of motion is the timing-function (easing). It decides how speed is distributed through the change, and even with the same time and distance, the pacing completely changes the feel.

  • linear: constant speed from start to finish. Tends to feel mechanical and stiff.
  • ease: starts slow, speeds up, then slows to a stop. The default, and natural in many cases.
  • ease-out: starts fast and slows to a stop. Often feels pleasant for UI entering or hover.
  • ease-in: starts slow and ends fast. Suits exits and disappearing motion.

Real objects do not suddenly burst to top speed and stop dead; they gradually accelerate and gradually decelerate. That is why the paced ease and ease-out feel more "natural" than linear. When in doubt, try ease-out for UI entrances and hover, and it will often settle in smoothly.

For finer control, you can define your own easing curve with cubic-bezier(). Four numbers shape the curve, but it is hard to picture the motion from the numbers alone. So the reliable way is to drag the curve visually in the cubic-bezier Generator, confirm the motion, and copy the generated value. Even a slightly "bouncy" motion can be expressed, depending on the shape of the curve.

Another tip is timing. A UI change that is too long feels like waiting, while one that is too short goes unnoticed. For small changes like hover, about 0.15 to 0.3 seconds is a comfortable guide. You can grasp how it actually looks by combining duration and easing in the cubic-bezier Generator.

Performance Pitfalls

Transitions are easy to use, but choosing the wrong property to animate can cause jank (stutter). To keep motion smooth, the crucial choice is "which property to animate."

Depending on the property change, the browser performs "layout (recomputing position and size)," "paint (drawing)," and "composite (compositing layers)." Of these, recomputing layout is the heaviest, and changing width, height, top, left, or margin every frame easily causes stutter because the work cannot keep up.

By contrast, transform (move, scale, rotate) and opacity can be handled by compositing alone, without redoing layout or paint, and GPU acceleration tends to help, so they animate smoothly. The following swaps are therefore effective:

  • Moving position: use transform: translate() instead of top/left
  • Changing size: use transform: scale() instead of width/height
  • Fading in or out: change opacity

In addition, transition: all cannot narrow its targets and may animate unexpected properties, so it is safer to name the property you want to change. Also, as a courtesy to users who are sensitive to motion, consider the prefers-reduced-motion media query to tone animations down.

A CSS transition is a simple mechanism that merely interpolates a state change over time, yet it is a foundational technique that greatly elevates the impression of a UI. Start by trying hover changes in the Button Generator and easing curves in the cubic-bezier Generator, and get a feel for what makes motion pleasant.

Please note that this article is intended to provide general information. CSS specifications and browser support can change over time. When implementing, make your decision after checking the latest official documentation and support status.

FAQ

What is a CSS transition?

A transition is a mechanism that, when a CSS property value changes, does not switch instantly but interpolates the change smoothly over a time you specify. It fires when state changes, such as on hover, focus, or a class toggle. Once you set the before and after values and the duration, the browser computes the in-between motion automatically.

Why does not my transition work even though I wrote it?

The most common cause is that transition-duration is unspecified and defaults to 0s. You must specify a time to get motion. Also, write the transition on the normal state side (writing it only on :hover means no motion on leaving), and note that toggling display:none cannot be animated.

How do I choose between transition and animation?

A transition suits simple two-point changes that react to user actions like hover or click. If you need automatic playback on page load, infinite repetition, or motion that passes through several stages, you need animation (@keyframes). As a guide: transition for UI state changes, animation for decoration and loading.

Which properties should I animate to keep motion smooth?

transform (move, scale, rotate) and opacity are best. They can be handled by compositing alone without recomputing layout, and GPU acceleration tends to help, so they stutter less. Swap top/left for transform:translate() to move, and width/height for transform:scale() to resize.

Do the WAZA TOOLS Button Generator and cubic-bezier Generator send my data?

Both run entirely in your browser, so what you enter and the code you generate are never sent to or stored on a server. They work on smartphones too, and you can try hover motion and easing curves as many times as you like, for free, so you can use them with confidence.