A hover color need not snap from one value to another. A CSS transition tells the browser to interpolate a property when its value changes, whether a pseudo-class changes the style or JavaScript adds or removes a class. Put the transition on the element’s usual rule, not only its hover rule, so the change is smooth in both directions. section 15.1
A button that changes shape and color
Give a button a teal background and add `transition: border-radius 0.3s linear, background-color 0.6s ease;` to its normal rule. In `button:hover`, set a rounded border and a red background. The comma-separated shorthand gives each property its own duration and timing function. The corners can transition even if the normal rule never explicitly sets `border-radius: 0`; the button already has an initial value. Moving the pointer away reverses both changes. section 15.1
Each shorthand entry names a property, a duration, a timing function, and optionally a delay. `all` can select every changing property, but naming properties lets different changes run differently. A timing function controls the rate: `linear` stays steady, `ease-in` accelerates, and `ease-out` decelerates. A custom `cubic-bezier()` curve can even make a moving label overshoot its destination before settling. section 15.1 section 15.2 section 16.2.2
When a transition does not produce the intended effect, check what is changing:
- A dropdown faded with `opacity` is still present while transparent and can cover a link beneath it. Pair opacity with `visibility`: delay hiding until the fade-out finishes, but remove that delay when opening. section 15.3.2
- A height cannot interpolate from `0` to `auto`. For a sliding dropdown, read its `scrollHeight` in JavaScript and set an explicit pixel height when opening; return it to zero when closing. section 15.4
- For a growing navigation icon, transition a scale transform rather than its width and height so neighboring elements do not shift. Apply the effect for keyboard focus as well as hover. section 16.2.1
Listing 15.9 Using a transition delay to manipulate when visibility changes
.dropdown__drawer {
position: absolute;
background-color: var(--background-color);
width: 10em;
visibility: hidden; #1
opacity: 0; #1
transition:
opacity 0.2s linear,
visibility 0s linear 0.2s; #2
}
.dropdown.is-open .dropdown__drawer {
visibility: visible; #3
opacity: 1; #3
transition-delay: 0s; #4
}
The dropdown rules show why the shorthand includes two entries: opacity fades for 0.2 seconds, while visibility switches after that delay on closing. The open rule removes the delay. section 15.3.2
Keep motion purposeful. Hover effects commonly take about 200–500 ms; longer changes can feel slow. A `prefers-reduced-motion: reduce` rule can shorten transition durations for people requesting less motion. Let CSS perform the interpolation even when JavaScript must coordinate the state or supply a measurable value. section 15.3 section 15.1 section 15.4




