Command Palette

Search for a command to run...

Hectal
Shots in this scene
SHOT 3.4Beginner ~21 min · shot 4 of 6

Reversing and Interrupting

In one line

When a change arrives while a transition is running, the browser starts the new transition from the value on screen. If the change goes back to where it started, the new transition is shortened so the element does not take longer to return than it took to leave.

0/6 · 0%

Think of it like this

You are walking to a shop and half-way there you remember something and turn back. You do not teleport to the start, and you do not walk the whole distance again at the start. You turn around where you are and walk back the part you covered. A reversed transition does exactly that.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

reversing shortening factor
The scaling the browser applies to the duration of a transition that returns to its start value, based on how far the first transition had got.
interrupt
A change that arrives while a transition is still running.
current value
The value the property has on screen now. A new transition starts from it.
(hover: hover)
A media query that is true when the main input can hover, such as a mouse and false on most touch screens.

Step by step

01Reverse at the start, the middle and the end

In "Interrupt a move" slow to 0.25×, press Go, and press Back early. The new track is short, because the box has hardly moved. Try again and press Back late: the track is nearly the full length.

02Read the new duration

Click the new track. With ease and a 1000 ms move, pressing Back at 200 ms gives a track of about 295 ms. Pressing at 800 ms gives about 976 ms.

03Retarget instead of reversing

Press Go, then Elsewhere at 200 ms. The box turns smoothly towards 100 px and the new track is the full 1000 ms.

04Sweep the strip

In "Fast toggles" move the pointer across the cells. Each one starts its own track and reverses it when you leave. Read the console for what several toggles in one frame do.

05Park the pointer

In "The doom flicker" place the pointer on the lower edge of the Bad card and keep it still. The count under it climbs without you moving. Do the same on Good: it stays at 1.

Try it yourself

  1. 1

    Reverse at 200 ms and at 800 ms

    In "Interrupt a move" use 0.25× and the pause button to press Go and then Back about 200 ms into the move. The new transform track reads about 295 ms. Repeat at 800 ms: about 976 ms. Then change ease to linear and reverse at 400 ms: about 399 ms, the same as the elapsed time.

  2. 2

    Retarget half way

    Press Go, then Elsewhere at about 200 ms. The box was at about 59 px and keeps moving smoothly towards 100 px. The track is 1000 ms again, so the last part is slow. About 700 ms after the retarget it is at 97.5 px of 100.

Code & diagrams

Interrupt a move

A 1000 ms ease move. Go, Back and Elsewhere can be pressed at any time. Use the timeline to pause and read each new track's duration.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.
Fast toggles

Nine hover cells, and an audit of how many tracks N toggles in one frame make. Sweep the pointer over the cells to see reversing in action.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.

Expected console output

1 toggle(s) in one frame: 2 track(s)
2 toggle(s) in one frame: 0 track(s)
3 toggle(s) in one frame: 2 track(s)
6 toggle(s) in one frame: 0 track(s)
The doom flicker

Both cards lift 30 px on hover. The Bad card lifts itself, so its hit area leaves the pointer. The Good card lifts a child inside a wrapper that stays put. The counts show enter and leave events.

Press Run to see the page.
00:00.000
animations
0.00s0.10s0.20s0.30s0.40s0.50s0.60s0.70s0.80s0.90s

Nothing is moving yet. Hover, click or scroll the page: every animation it starts shows up here as a track.

frames

Console

Nothing logged yet.

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

Hover that moves the thing you hover

In "The doom flicker", use the Bad card: .bad:hover { transform: translateY(-30px); }.

terminal
$ Park the pointer on the card's lower edge and watch the count under it
── what you'll see ──
The card shakes up and down and the count under it keeps climbing while the mouse stays still. A measurement in Chromium 153 with a still pointer 3 px above the card's lower edge: about 80 enter and leave events in about 1.6 s.

Myth vs fact

Myth

Hovering out always takes as long as hovering in.

Fact

A reversed transition is shortened to the distance already covered, so an early hover-out returns quickly.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    A shortened duration is visible on the track: a track that reads about 295 ms when the CSS says 1000 ms is the sign of a reversed transition. Look for it when a hover-out seems to take the wrong time.

  • ▸

    A transition that is interrupted is cancelled, which dispatches transitioncancel (Topic 3.5), then a new one is run. Code that listens for transitionend to finish an exit will never hear it for a transition that was reversed.

Remember this

  1. 1

    The problem this solves: users do not wait for animations. They hover and leave, press and press again, open and close. If every interruption jumped to the end or restarted from the beginning, the interface would twitch. The browser's rules make interruptions smooth without any code from you, provided you know them.

  2. 2

    The new transition starts from the value on screen. When the target changes mid-way, the old transition is cancelled and the new one starts from the property's current computed value, not from its old start or its old end. Measured with a 1000 ms ease move to 200 px, retargeted to 100 px at 200 ms: the box was at 59.05 px and the new 1000 ms transition began from 59.05 px, with no jump.

  3. 3

    Reversing is shortened. If the new target is the value the old transition started from (it is going back), the browser applies a reversing shortening factor: the new duration is scaled by how far the old transition had got, measured on the eased progress and not on time. With a linear curve, reversing at 400 ms of 1000 ms gave a 399 ms transition. With ease, reversing at 200 ms gave about 295 ms, because ease had already covered about 29% of the distance. Reversing at 800 ms gave about 976 ms, since ease is nearly done by then.

  4. 4

    Only the exact return reverses. If the new target is a different value (100px instead of the start), it is a new transition with the full duration, measured from the current value. The distance is shorter, so it feels slower per pixel. That is how the third button in the first example behaves.

  5. 5

    Several changes in one frame count as one. The browser compares the style at the end of a frame with the style at the end of the last one. Toggling a class twice in the same script is no change; three times is one change. In the audit below, one toggle made two tracks, two toggles made none, three made two, six none. This matters for code that flips a state quickly and expects each flip to show.

  6. 6

    The doom flicker. If hovering an element moves it, the pointer can end up outside it. The hover ends, the element moves back, the pointer is over it again, and the loop runs. With the pointer parked 3 px above the lower edge of a card 32 px high that lifted 30 px on hover, Chromium reported about 80 enter and leave events in about 1.6 seconds without the mouse moving (measured). A lift of 4 px did not flicker: the pointer stayed inside the card. Put the hover on a wrapper that does not move, and move the child. The wrapper's hit area stays under the pointer (one enter event, in the same test).

  7. 7

    Touch devices have no hover. On a phone a tap sets :hover and it can stick after the finger lifts. Wrap hover-only styling in @media (hover: hover), so touch users never see a half-applied hover. In a touch-emulated browser the media query answered false (measured), and the hover rules did not apply. The press (:active) is the touch feedback (Topic 3.6).

Explain it without notes

01

A user hovers a card for 100 ms of a 400 ms transition and leaves. How long does the return take, and why?

02

Why can a card that lifts on hover flicker, and what is the fix?

03

What does @media (hover: hover) protect against?

Practice

01

Make a card that lifts 6 px on hover without flicker, using a wrapper.

02

A menu opens with a 300 ms transition and closes with the same one. A user clicks open, then close at 100 ms. Describe what the browser does with the closing transition.

Done when you can

  • You can say where a new transition starts when it interrupts another

  • You can explain the reversing shortening factor with a number

  • You can find and fix a hover that moves away from the pointer

  • You wrap hover-only styling in a (hover: hover) query