Shots in this scene
Your First Transition
In one line
A transition tells the browser to take time over a style change instead of jumping. The browser starts one when a style changes on a frame, and it reads the transition settings from the new style, so the rule must sit on the right selector.
Think of it like this
A light switch changes a room from dark to bright in one instant. A dimmer knob changes it gradually. A CSS transition is a dimmer fitted to a property. You still flip the state (dark, then bright), but you have told the browser how long to take getting there.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- transition
- An instruction to take time over a change of one or more CSS properties, instead of changing in a single frame.
- style change
- A property's computed value being different from the value it had after the previous frame, whatever caused it (hover, class, script, media query).
- CSSTransition
- The browser's object for one running transition of one property on one element. It is what you see as a track on the Motion Timeline.
- shorthand
- One property that sets several at once.
transition: opacity 200ms ease-outsets the property, duration and timing function together.
Step by step
01Read the settings
Run "Your first transition". The console prints the four longhand values the browser has for the pill: property: background-color, color, duration 0.2s, timing ease-out, delay 0s. It also prints tracks at load: 0: nothing animates until something changes.
02Cause a change and find the tracks
Press Toggle the .hot class. Two tracks appear, transition · background-color and transition · color, each 200 ms long. One change of class made two transitions, one per property.
03Slow it down and step through
Press 0.1× and toggle again. Click a track to see its graph: ease-out rises quickly and flattens. At 100 ms (half the time) the background is already about two thirds of the way to orange.
04Run the audit
Open "When does a transition start?". Its console counts the tracks after six different changes. Only two of the six make a transition. The text under that example explains each line.
Try it yourself
- 1
Animate only the background
In "Your first transition", change
transition-property: background-color, color;totransition-property: background-color;. Press Toggle the .hot class: only one track appears, and the text is already white while the background is still white. Frozen 100 ms in, the background isrgb(255, 154, 111)and the text isrgb(255, 255, 255): pale text on a pale orange background. With both properties listed, at the same moment the text isrgb(183, 183, 185), a grey in between. - 2
Make the duration zero
Change
transition-duration: 200ms;totransition-duration: 0s;and toggle. No track appears and the colours change in one frame: the timeline stays empty ((no animations)in the tool). A transition with no duration is never created.
Code & diagrams
The pill changes colour when you hover it or press the button. Look at the console for the four settings, then pause and step through a change on the timeline.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
property: background-color, color
duration: 0.2s
timing: ease-out
delay: 0s
tracks at load: 0Press the three buttons to see each box move (A both ways, B only one way, C not at all). The console audit builds fresh boxes and counts the tracks the browser makes. Every line is a rule from the text above.
Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.
Console
Nothing logged yet.Expected console output
A, class added: 1
B, class added: 1
B, class removed: 0
C, 0ms, class added: 0
A, inserted already .on: 0
A, added and removed one frame: 0Hover each button. Which one feels like it answers your pointer?
A A
B B
Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Put the transition on the hover rule only
In "Your first transition", delete the four transition-* lines from .pill, and add transition: background-color 200ms ease-out, color 200ms ease-out; to the .pill:hover, .pill.hot rule instead.
Break #2
Leave out a unit
Replace the four longhands with transition: background-color 200, color 200;.
Myth vs fact
Myth
A transition plays whenever a property changes.
Fact
It plays when a property changes on a frame the browser has seen before, and the new style declares a duration above zero. Elements that appear in their final style, and changes that undo themselves inside one frame, do not animate.
Myth
Put the transition on :hover so it only runs on hover.
Fact
It then runs in one direction only. Put it on the normal rule, so it describes the element, and let the state rules change values.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
The browser decides at style recalculation, once per frame, by comparing the before-change and after-change computed styles. That is why
void el.offsetWidth(forcing a style recalculation) between two changes in the same script makes them two separate changes, and why two toggles without it can cancel to nothing. Phase 6 covers the cost of forcing it. - ▸
A transition of
transformoropacitycan run on the compositor thread (Topic 6.1). What a colour costs depends on the property: in Chromium 153background-coloris composited, whilecolorandbox-shadowrepaint. Read the cost colour on the timeline instead of guessing (Topic 6.2).
Remember this
- 1
The problem this solves: without a transition, a hover colour, a pressed button or a focused field changes in a single frame. The eye is poor at noticing instant changes, and a hard cut feels abrupt. A transition spreads the change over 100 to 300 milliseconds, long enough to see, short enough to stay out of the way. The CSS course (Topic 10.1) showed the syntax; this topic looks at what the browser really does.
- 2
Four properties and a shorthand.
transition-propertynames what to animate (background-color, color).transition-durationsays how long (200ms).transition-timing-functionis the curve (ease-out; Phase 5 covers curves).transition-delaywaits before starting. The shorthandtransition: background-color 200ms ease-outsets them together. In the shorthand the first time value is the duration and the second is the delay, soopacity 200ms 50mswaits 50 ms. - 3
The defaults animate nothing. The initial value of
transitionisall 0s ease 0s: every property, zero duration. A zero duration means the change is instant, so with notransitionrule you never get one. You always have to set a duration. (The timeline shows no track at all for a 0 s transition: the browser does not even create one.) - 4
A transition starts on a style change. The browser computes every element's style once per frame. If an element's computed value for a property differs from the value it had after the previous frame, and the new style has a transition for that property with a duration above zero, the browser creates a
CSSTransitionobject, one per changed property. It appears on the timeline astransition · background-color. What caused the change does not matter::hover,:focus,:active, a class added by JavaScript, a media query that starts to match, or a script writingstyle.opacity. - 5
Which style supplies the settings: the new one. The browser reads the
transitionvalues from the style the element has after the change. So a transition written on the element's normal rule (.pill { transition: … }) plays in both directions, because the normal rule applies before and after. A transition written only on.pill:hoverplays when you hover in. When you hover out, the hover rule stops applying, the new style has no transition, and the colour snaps back at once. This is the most common transition bug, and the second example below shows it. - 6
When no transition starts. There is no change to animate when an element first appears already in its final style (nothing came before it). Two changes inside the same frame that return to where they began count as no change at all, because the browser only compares the style at the end of the frame with the style at the end of the last one. A duration of zero and an invalid declaration also give nothing:
transition: color 200(no unit) is thrown away whole, and the element keepsall 0s ease 0s.
Explain it without notes
Why does a transition written only on :hover play when you hover in but not when you hover out?
A developer says: my transition does not run on page load, so it is broken. What really happens?
What is the value of transition when nobody wrote one, and what does it mean for animating?
Practice
Write the CSS for a .badge that fades its background from grey to orange over 160 ms with ease-out when it gets the class .new, and back again when the class is removed.
A link a.more changes colour on hover, but the colour snaps back when the pointer leaves. Find the bug in a.more:hover { color: #ff6b2c; transition: color 200ms; } and fix it.
Done when you can
You can name the four transition properties and what the shorthand's two time values mean
You can explain why the transition goes on the base rule
You can say when the browser does not create a transition (zero duration, first style, a change undone in one frame)
You can find the tracks of a transition on the timeline and read its duration and easing