📜 WAYPOINT LESSON
How Browsers Render (and Where It Janks)
⭐⭐ intermediate⏳ 20 min read📍 Lesson 105 of 143
Parse → style → layout → paint → composite. Knowing which step your code triggers tells you what it costs.
Every visual change walks a pipeline. The step that re-runs determines the cost.
The pipeline
- Parse — HTML becomes the DOM; CSS becomes the CSSOM. Scripts can block parsing (hence
defer/async). - Style — compute which CSS rules apply to each element (the "Recalculate Style" you see in DevTools).
- Layout — geometry: where every element sits, how big it is. A change to size or position invalidates layout.
- Paint — fill pixels: text, colors, shadows, images.
- Composite — GPU-assembles painted layers. Cheapest of all.
Cost ordering matters: a transform or opacity change can stop at composite (cheap). A width/top/font-size change walks style→layout→paint (expensive — it's on every element it affects, and children). color/background skips layout but still paints.
Jank and the frame budget
Browsers aim for 60fps — every frame gets a 16.7ms budget (10ms on 120Hz displays). A script task that runs 200ms freezes that many frames: the page visibly stutters. Long tasks come from big loops, huge DOM mutations, or layout thrashing.
Layout thrashing: the classic performance bug
// BAD: read-write-read-write forces layout every iteration
for (const card of cards) {
const h = card.offsetHeight; // READ — forces layout (previous write is pending)
card.style.height = h + 20 + "px"; // WRITE — invalidates layout
}
The fix is batching: read everything, then write everything.
const heights = cards.map((c) => c.offsetHeight); // all reads
cards.forEach((c, i) => {
c.style.height = heights[i] + 20 + "px";
}); // all writes
What actually moves the needle
visibility/opacitytransitions instead of size animationscontent-visibility: autofor long off-screen sections- Fewer, larger DOM mutations (DocumentFragment, one reflow)
- The Composite-only properties (
transform,opacity) for animation
⚡ Now practice
Ready to CodeRender Pipeline — PracticeClassify property costs, batch reads/writes to kill thrashing, and count frames honestly.
3 challenges · · ~18 min