Command Palette

Search for a command to run...

Hectal
Shots in this scene
SHOT 6.1Intermediate ~19 min · shot 1 of 7

The Rendering Pipeline in Depth

In one line

A frame is style, layout, paint and composite. Some of that runs on the busy main thread and some on the compositor thread, which is why a transform animation can keep moving while a left animation freezes.

0/7 · 0%

Think of it like this

A restaurant. The waiter (the main thread) takes orders, decides where every table goes and fills the plates. A conveyor belt (the compositor) carries finished plates to the tables. If the waiter is stuck in a long argument in the kitchen, plates already on the belt keep riding. But a change that needs the waiter, such as moving a table, waits until the waiter is free.

Words you'll meet

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

main thread
The one thread that runs your JavaScript, style, layout and paint. A long task on it blocks everything else on it.
compositor thread
A second thread that stacks painted layers and can move, scale and fade them without the main thread.
layout
Working out the size and position of every box on the page. One change can move many boxes, so it can cost the most.
paint and raster
Paint records what to draw; raster turns that into pixels. Together they draw an element's look again.
composite
Stacking painted layers (with their transforms and opacity) into the final picture.
jank
Visible stutter: a frame that arrives late or not at all.

Step by step

01Follow one frame

On a 60 Hz screen the browser gets 16.7 ms per frame. Each frame it runs your timers and requestAnimationFrame callbacks, then style, layout and paint on the main thread, then composite on the compositor thread. If the main-thread part runs past the deadline, that frame is late.

Follow one framediagram
Rendering diagram…

02Start with the widget

Choose transform, then left in the widget below, and switch on main thread busy: the left lane misses frames and the transform lane does not.

03Prove it in the page

In "A busy main thread" the left track is red and the transform track is green. Press the button at 1× (not paused).

04Check who drives the animation

In "Who runs it?" CSS, the Web Animations API and a requestAnimationFrame loop all move transform. Only the loop box stops.

Try it yourself

  1. 1

    Freeze one box, not the other

    In "A busy main thread" press the block button while the boxes move. In a screen recording in headless Chromium, the blue transform box showed 29 frames of movement during the block and the orange left box none.

  2. 2

    Count the animations the browser knows

    In "Who runs it?" the console says animations the browser knows about: 2. Press the button: the CSS and WAAPI boxes kept moving (29 frames each) and the requestAnimationFrame box showed none.

Code & diagrams

Try it: interactive

The frame, step by step

Pick transform, then left, then switch on the busy main thread. Watch which lane misses frames. (Its stage times are illustrative, not measured.)

A busy main thread

Press the button at 1×: the orange box (left) freezes for 600 ms, the blue one (transform) keeps moving. The busy loop stops itself after 3 million turns, so a paused timeline cannot hang it.

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

animations: 2
Who runs it?

CSS and the Web Animations API show up on the timeline as tracks (2 animations). The requestAnimationFrame loop does not: the browser does not know it is an animation, and it stops when the thread is busy.

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

animations the browser knows about: 2

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

Drive the transform from JavaScript

In "A busy main thread", replace the CSS via-transform keyframes with a requestAnimationFrame loop that sets style.transform (as the green box in "Who runs it?" does).

terminal
$ Press the block button and watch the box
── what you'll see ──
It freezes like the `left` box: no frames of movement during the block, against 29 for the CSS `transform` animation.
Screen recording, headless Chromium.

Myth vs fact

Myth

Anything animated with transform is always smooth.

Fact

Only when the browser drives it. A transform set from a requestAnimationFrame loop stops when the main thread is busy.

Remember this

  1. 1

    The problem this solves: an animation that is smooth on your laptop can stutter on a phone, and your own page code can freeze one animation but not another. Until you know the steps of a frame and who does them, this looks random. With the steps, it is predictable.

  2. 2

    The steps of a frame. (1) Style: the browser works out which CSS rules apply to each element and what the values are right now. (2) Layout: it works out the size and position of every box. (3) Paint: it records what to draw (text, borders, backgrounds, shadows) for each layer. (4) Raster: it turns those drawing instructions into pixels, tile by tile, usually on the GPU. (5) Composite: it stacks the layers, moving, fading or transforming them, and sends the picture to the screen. (Recall from Topic 1.4: you met these steps in plain words. Here we open each one.)

  3. 3

    Two threads that matter. The main thread runs your JavaScript, style, layout and paint. It does one thing at a time, so a long task blocks everything else on it. The compositor thread only stacks layers that are already painted. It can move, rotate, scale and fade a layer without asking the main thread, and it also drives scrolling.

  4. 4

    Which animations run on the compositor. A CSS animation, a CSS transition or a Web Animations API animation of transform or opacity can. Hectal's measured table in Topic 6.2 adds a few more in current Chromium. An animation written in JavaScript (a requestAnimationFrame loop that sets style.transform) cannot, because the main thread must run that code every frame. Who drives the animation matters as much as the property.

Explain it without notes

01

Name the steps of a frame and say which run on the main thread.

02

Why can a CSS transform animation keep moving while a 600 ms task runs, but an identical left animation stops?

Practice

01

In "Who runs it?" add a fourth box animated with the translate property (translate: 150px 0) by CSS, and a button that blocks the thread. Does it keep moving?

02

Write a busy(ms) function and describe how you would use it to test whether a given animation survives a busy main thread.

Done when you can

  • You can name the five steps of a frame

  • You can say which thread runs each step

  • You know which kinds of animation can run on the compositor

  • You can show with a busy-loop test whether an animation survives a busy page