From URL to pixels
When HTML arrives, the browser runs a precise pipeline — parse, style, lay out, paint and composite. Understanding it explains why pages feel fast or slow, and which fixes actually help.
In this lecture you will
- Describe the stages of the browser rendering pipeline
- Explain how the DOM and CSSOM combine into the render tree
- Explain why CSS blocks rendering and how scripts can block parsing
- Relate layout and paint work to page performance
The Networking course follows a request until the server’s response arrives. This lecture picks up from there. The browser now holds a stream of bytes — and has to turn them into pixels on your screen, fast enough that the page feels instant. How it does that shapes almost every performance decision in web development.
The critical rendering path
Browsers follow a well-defined sequence, often called the critical rendering path. Scroll through it with a tiny page.
- 1Bytes arrive
The HTML response arrives as bytes. The browser decodes them into characters and starts parsing immediately — it doesn’t wait for the whole file.
- 2Parse HTML into the DOM
Tags become a tree of objects: the Document Object Model. Every element, attribute and piece of text is a node, and nesting in the HTML becomes parent–child links in the tree.
- 3Parse CSS into the CSSOM
Stylesheets are fetched and parsed into the CSS Object Model. Rendering waits for CSS, because showing unstyled content and then restyling it would look broken.
- 4Build the render tree
DOM and CSSOM combine into the render tree: only visible elements, each with its final computed style. The head and the display:none promo are left out.
- 5Layout
The browser computes the exact position and size of every box, starting from the viewport — here, a flex container placing the paragraph and image side by side.
- 6Paint and composite
Boxes are painted into layers of pixels — backgrounds, text, images — and the compositor stacks the layers into the final frame shown on screen.
What blocks rendering
Two resources can hold everything up:
- CSS is render-blocking
- The browser won’t paint until the CSS it knows about has loaded. Keep critical CSS small and avoid chains of stylesheets importing stylesheets.
- Scripts can block parsing
- A plain script tag pauses HTML parsing until the script has downloaded and run, because the script might change the document.
- defer
- Downloads the script in parallel and runs it after parsing finishes, in order. The right default for most scripts.
- async
- Downloads in parallel and runs as soon as it arrives, in any order. Good for independent scripts such as analytics.
<head>
<link rel="stylesheet" href="/site.css">
<script src="/app.js" defer></script>
<script src="/analytics.js" async></script>
</head>
See the difference on a network waterfall. Switch how app.js is loaded and watch three moments move: the first paint, DOM ready (when the HTML has been fully parsed and deferred scripts have run) and the largest contentful paint — here, the hero image:
Timings are illustrative, but the rules are the browser’s. A plain script in the head roughly doubles the time to first paint here. A CSS file that @imports another adds a second round trip before anything can render. Preloading tells the browser about the hero image before the parser reaches it.
Layout, paint and composite — the ongoing costs
The pipeline doesn’t just run once. Whenever JavaScript or user interaction changes the page, some of it runs again:
- Changing geometry — width, height, margins, adding elements — triggers layout for the affected boxes, then paint and composite. On large pages, layout is expensive.
- Changing appearance only — colour, background — skips layout but needs paint.
- Changing transform or opacity can often be done by the compositor alone, usually on the GPU, without layout or paint. That is why smooth animations move things with
transforminstead oftopandleft.
To stay smooth, a browser must produce a new frame about every 16.7 milliseconds (60 frames per second). Pick a property to animate and see which stages run on every frame — then grow the page and switch to a slower phone:
Millisecond costs are illustrative; which stages run is not. Layout work grows with the page, so an animation that is smooth on a small demo can stutter on a real product page — and a budget phone has several times less time to spare. Measure in the Performance panel of your browser’s developer tools.
Measuring what users feel
Google’s Core Web Vitals turn the pipeline into user-centred metrics that many teams track:
- LCP — Largest Contentful Paint: how soon the main content appears.
- INP — Interaction to Next Paint: how quickly the page responds to clicks and taps.
- CLS — Cumulative Layout Shift: how much content jumps around while loading.
Next, we look closely at the first structure the browser builds — the DOM — and pull a real page apart in 3D.
Key takeaways
- The browser turns HTML into the DOM and CSS into the CSSOM, then combines them into a render tree of visible elements.
- Layout calculates the size and position of every box; paint fills in pixels; compositing assembles layers into the final frame.
- CSS is render-blocking and plain script tags pause HTML parsing — use defer, async and lean critical CSS.
- Changing geometry triggers layout; animating transform and opacity can be handled by the compositor alone.
Check your understanding
3 questions · answers explainedQ1What does the render tree contain?
Q2Why is it usually better to add defer to a script tag in the head?
Q3Which animation is typically smoothest?