Command Palette

Search for a command to run...

Hectal
Shots in this scene
SHOT 19.4Advanced ~20 min · shot 4 of 6

Debug the Jank

In one line

A small panel with four motion bugs: a layout animation, layout thrashing, a leak and no reduced-motion version. Find each one with the Motion Timeline and a counter, fix it and prove it.

0/6 · 0%

Think of it like this

A mechanic does not replace parts at random. She reads the warning lights, checks one system at a time and tests after each repair. Debugging motion is the same: one symptom, one tool, one fix, one proof.

Words you'll meet

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

thrashing
Reading a layout value and writing a style over and over, so the browser lays out again each time.
leak
Something a removed or hidden part started that is still running, such as an endless animation on an invisible element.
regression
A bug that comes back after a fix. A count or a check stops it returning unnoticed.
pause control
A button that stops motion which starts by itself and lasts over five seconds.

Step by step

01Run the broken panel

Run "The panel with four bugs". The console says tidy: 40 reads, 39 forced layouts at once: bug 2 is caught. Press Charge, Sparkle twice, then Clear.

02Read the tracks

After Charge there is a red width track. After Clear two i.gone tracks still run, and the badge's ∞ track never stopped. Switch on Reduced motion: the badge still pulses.

03Run the fixed panel

"The panel, fixed" prints tidy: 40 reads, 0 forced layouts. Charge gives a green transform track, Clear leaves no i tracks, Reduced motion removes the badge track, and Pause motion freezes it.

04Fix it yourself

The exercise "Fix the four bugs" starts from the broken panel and checks all four fixes, including a reduced-motion run.

Try it yourself

  1. 1

    Count the dots

    In the broken panel press Sparkle five times, then Clear. Five i.gone tracks remain: every press adds one that nothing will ever stop.

Code & diagrams

The panel with four bugs

Press Charge, Sparkle twice and Clear, then read the timeline: one red track, two endless tracks on hidden dots, and the badge's endless track.

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

tidy: 40 reads, 39 forced layouts
The panel, fixed

The same four actions. Compare the tracks, then switch on Reduced motion and press Pause motion.

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

tidy: 40 reads, 0 forced layouts

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

Cancel but do not remove

In the fixed panel's Clear, delete dot.remove(); and keep the cancel() call.

terminal
$ Press Sparkle twice, then Clear, and read the timeline
── what you'll see ──
dots in DOM: 2 (and no i tracks on the timeline)
From the timeline and the DOM: cancelling frees the animation, but the nodes pile up.

Myth vs fact

Myth

If it is hidden with opacity 0, it costs nothing.

Fact

Hidden is not stopped. The timeline lists the animations on i.gone as running. Stop or remove what nobody can see.

Remember this

  1. 1

    The problem this solves: "it feels janky" is not a bug report. Four causes look alike on a phone, and fixing the wrong one wastes a day. Each leaves a different mark you can learn to read.

  2. 2

    Bug 1, a layout animation. The meter fills with width: the timeline shows a red CSSTransition [width] track and the costs layout badge. Fix: a full-width child scaled with transform: scaleX() from the left. Bug 2, thrashing. Tidy reads offsetHeight and writes style.height row by row. It leaves no track, so the counter says 40 reads, 39 forced layouts. Fix: read all, then write all: 0 forced.

  3. 3

    Bug 3, a leak. Clear fades the sparkles to opacity: 0 but never stops them: the timeline still lists two Animation i.gone [transform] ×infinite tracks, invisible endless work. Fix: cancel each animation and remove the node. Bug 4, no reduced motion and no pause. The badge pulses for ever, and with Reduced motion on its ∞ track keeps running. Fix: no animation inside the reduce query (the badge stays visible) and a pause control (WCAG 2.2.2).

  4. 4

    Prove it. After each fix run the same read: the red track is gone, the forced count is 0, no i tracks remain after Clear, and the reduced run shows no movement. A fix without its proof is a guess.

Explain it without notes

01

How do you tell a layout animation from a paint or composite one on the timeline?

02

A page janks only after the visitor has used it for a while. What do you look for?

Practice

01

A modal adds a resize listener when it opens and never removes it. Fix it and say how you would test it.

02

Sparkles are driven by a requestAnimationFrame loop that never ends after Clear. Fix it.

Done when you can

  • You can name the mark each of the four bugs leaves

  • You can fix each one and show the proof

  • You know thrashing needs a counter, not the timeline

  • You know a leak has a running half and a held half