How Browsers Render Pages: From HTML Parsing to GPU Composition

This article walks through the complete browser rendering pipeline—HTML parsing, CSS rule construction, layout, paint, layer creation, rasterization, and compositing—explaining each step, the underlying data structures, performance implications, and practical tips for optimizing rendering in modern web applications.

ELab Team
ELab Team
ELab Team
How Browsers Render Pages: From HTML Parsing to GPU Composition

Preface

Browser rendering is a broad and deep topic; each sub‑topic could fill an entire discussion. This article provides a high‑level overview of the whole rendering process, referencing the GeekTime column "Browser Working Principles and Practice" and reusing several illustrative images.

Overall Process

Parse HTML and build the DOM tree

Parse CSS and generate the CSS rule tree

Merge DOM and CSS rules to create the Render tree (layout)

Paint the Render tree (pixel information)

Display the final result

1. Building the DOM Tree

The browser cannot directly understand raw HTML, so it converts the HTML byte stream into a DOM structure using an HTML parser (HTMLParser). The process includes decoding bytes to characters, tokenizing into tag and text tokens, and converting tokens to nodes that are pushed onto a stack to construct the DOM.

For a concrete implementation, see Vue.js's HTMLParser implementation [2].

2. Building the CSS Rule Tree

Similar to HTML, the rendering engine cannot directly use CSS text. It converts CSS into a stylesheet object (styleSheets) that can be inspected via document.styleSheets. The stylesheet hierarchy is visualized in the following image.

Applying inheritance and cascade rules, the engine finally produces a CSS rule tree that can be inspected in the Elements → Computed panel.

3. Layout

3.1 Constructing the Render Tree

The DOM describes the HTML structure, but many nodes are invisible (e.g., head, display:none) and some visual elements are not present in the DOM (e.g., pseudo‑elements). The engine traverses the DOM, discarding invisible nodes and adding missing visual nodes to produce a Render tree that contains only visible elements.

3.2 Calculating Layout Information

After the Render tree is built, the engine must compute the absolute geometric positions of each element. For example, a div with absolute positioning needs its x, y, width, and height resolved.

div { position: absolute; width: 100px; height: 100px; top: 10px; left: 10px; }

Determining these positions is complex because text flow, line breaks, and font sizes affect element dimensions.

Chrome engineers discuss layout challenges in the BlinkOn conference talks [4].

4. Paint

With the Render tree and layout information ready, the engine must paint elements in the correct order (e.g., sky before clouds). To handle complex effects such as 3D transforms, opacity animations, and z‑index ordering, the engine uses a layering mechanism.

4.1 Layers

Each DOM node gets a LayoutObject. LayoutObjects that share the same coordinate space are grouped into a Paint Layer. Paint Layers that meet certain criteria become Composite Layers (GPU layers).

Composite layers are created when any of the following conditions are met:

3D transform is applied

Opacity, filter, or transform has an active animation/transition will‑change is set to opacity, transform, top, left, etc.

Demo code for creating composite layers:

<!DOCTYPE html>
<html lang="en">
<head>
  <style type="text/css">
    *{margin:0;padding:0;}
    div{width:200px;height:100px;}
    .default{background:#ffb284;}
    .composite-translateZ{transform:translateZ(0);background:#f5cec7;}
    .composite-tansform-active{background:#e79796;transform:translate(100px,100px);transition:3s;}
    .composite-will-change{background:#ffc988;will-change:transform;}
  </style>
</head>
<body>
  <div class='default'>默认层</div>
  <div class='composite-translateZ'>合成层-translateZ</div>
  <div class='composite-tansform-active'>合成层——active transform(hover一下我)</div>
  <div class='composite-will-change'>合成层——will-change</div>
</body>
</html>

In Chrome DevTools → Layers, you can see the generated composite layers.

When an element overlaps another, it may be implicitly promoted to a composite layer to preserve correct rendering order.

<!DOCTYPE html>
<html lang="en">
<head>
  <style type="text/css">
    *{margin:0;padding:0;}
    div{width:200px;height:200px;}
    .bottom{background:#f5cec7;animation:anim-translate 3s ease-in-out alternate infinite both;}
    .top{background:#e79796;transform:translateY(-50px);}
    @keyframes anim-translate{from{transform:translateX(0);}to{transform:translateX(50px);}}
  </style>
</head>
<body>
  <div class='parents'>
    <div class="bottom">下层-有动画</div>
    <div class="top">上层-隐式提升为合成层</div>
  </div>
</body>
</html>

Because the top div overlaps the bottom one, it is implicitly promoted to a composite layer, which you can see labeled as "might overlap other composited content" in the Layers panel.

Render layers guarantee correct element order; composite layers reduce rendering cost by enabling GPU acceleration.

Composite layers are rasterized on the GPU, which is faster than CPU processing.

When repainting, only the affected layer needs updating.

Transforms and opacity on promoted layers are handled entirely by the GPU, avoiding layout and paint stages.

Therefore, for frequently moving elements, promote them to their own composite layer to improve performance.

4.2 Paint Execution

After layers are defined, the engine paints each layer in order, breaking the work into many small paint commands such as drawRect, drawTextBlob, drawPaint, and color specifications.

drawRect(rect, paint): draw a rectangle

drawTextBlob(x, y, paint): draw text starting at (x, y)

drawPaint(paint): fill the canvas

color: specified in ARGB format

For detailed command meanings, see the linked reference [7].

In DevTools → Layers → Paint Profiler, you can view the list of paint commands for a selected composite layer.

4.3 Rasterization

Paint commands are handed off to a raster thread, which converts them into bitmaps (often using the GPU). The raster thread processes tiles, prioritizing those in or near the viewport to avoid unnecessary work.

5. Composition and Display

After rasterization, each layer is a bitmap. The compositor thread merges these bitmaps into a final image, which is sent to the GPU’s back buffer. The GPU then swaps the back buffer with the front buffer, presenting the frame to the screen. If the compositor cannot keep up with the display’s 60 Hz refresh rate, visual stutter may occur.

To maintain smooth animation, the total time for all rendering steps should stay under 16.7 ms (1/60 s).

6. Related Topics

6.1 How CSS Affects DOM Construction

JavaScript can modify CSS, so a script that runs before the CSSOM is ready could affect DOM construction. Therefore, the CSS rule tree must be built before executing any JavaScript that might read or modify styles.

When a blocking script appears after a CSS file reference, the browser pauses DOM construction until the CSSOM is complete.

<!DOCTYPE html>
<html lang="en">
<head>
  <style type="text/css">h4{font-size:18px;font-weight:none;}</style>
  <link rel="stylesheet" type="text/css" href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/static/protocol/https/soutu/css/soutu_new2_ae491b7.css">
</head>
<body>
  <button id="btn">清空dom</button>
  <div>我是div</div>
  <!-- script blocks DOM construction -->
  <script>console.log('遇到内联script啦')</script>
  <div>我是div</div>
  <script type="text/javascript">
    let btn = document.getElementById('btn');
    let body = document.body;
    btn.addEventListener('click', function(){ body.innerHTML = ''; }, true);
  </script>
</body>
</html>

Testing on a slow network shows that when the script is present, subsequent div elements appear only after the CSS has loaded, confirming that CSS can block DOM construction via JavaScript.

6.2 Reflow, Repaint, Composite

Reflow changes element geometry and incurs the highest cost.

Repaint changes non‑geometric visual properties (e.g., color) and is cheaper.

Composite only triggers when a promoted layer’s transform or opacity changes; it bypasses layout and paint, offering the lowest cost.

Composite work runs on a separate thread, which is why CSS animations can stay smooth even when the main thread is blocked.

6.3 Layer Explosion

Overlapping elements can cause implicit composite layers, potentially leading to a large number of unexpected layers (“layer explosion”). To mitigate this, add explicit z-index to promoted elements and avoid creating unnecessary layers.

Use z-index to control overlap when promoting to composite layers.

Do not promote elements without analysis; each layer consumes memory and processing overhead.

References

GeekTime column – Browser Working Principles and Practice [1][9]

Vue.js HTMLParser implementation [2]

CSSOM details – https://www.cnblogs.com/xiaohuochai/p/5848335.html [3]

Few talks from BlinkOn Conference [4]

Stacking context – MDN [5]

Performance composite article – https://fed.taobao.org/blog/taofed/do71ct/performance-composite/ [6][10]

Canvas restore API – https://api.flutter.dev/flutter/dart-ui/Canvas/restore.html [7]

Layer explosion demo – http://fouber.github.io/test/layer/?size=20 [8]

Inside look at modern web browser (part 3) – https://developers.google.com/web/updates/2018/09/inside-browser-part3 [11]

Detailed discussion on layer compositing – http://jartto.wang/2017/09/29/expand-on-performance-composite/ [12]

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Performance OptimizationDOMpaintCSSOMcomposite layers
ELab Team
Written by

ELab Team

Sharing fresh technical insights

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.