How Blink Separates the DOM and Layout Trees in Chromium
This article explores how the Blink rendering engine in the Chromium browser separates the Document Object Model (DOM) tree from the Layout tree. By dividing the structural representation of a webpage from its visual geometry, Blink optimizes rendering performance, manages CSS styling efficiently, and handles non-visual elements seamlessly. Understanding this architectural separation clarifies how modern browsers translate raw HTML and CSS into the pixels seen on a screen.
The Purpose of Each Tree
The DOM tree and the Layout tree serve fundamentally different
purposes in Blink. The DOM tree is the parsed representation of the raw
HTML document. Constructed out of C++ Node objects, it
stores the hierarchical relationships between elements, attributes, and
text, acting as the primary interface for JavaScript manipulation.
Conversely, the Layout tree (historically referred to as the Render
tree) contains the visual and geometric information required to paint
the page. Built from LayoutObject instances, this tree
calculates and stores the exact widths, heights, and screen coordinates
of the elements that the user will actually see.
The Style Calculation Bridge
Blink separates these two trees through a process that occurs during
the style calculation phase. When Blink parses HTML, it builds the DOM
tree. Next, the engine parses the CSS and computes the final visual
rules for each DOM node, storing this data in a read-only object called
ComputedStyle.
Only after the style is computed does Blink decide whether to attach
a DOM node to the Layout tree. While a DOM Node holds a
pointer to its corresponding LayoutObject, the two remain
completely distinct data structures in memory. This separation allows
scripts to query or mutate the DOM without immediately triggering
expensive geometric recalculations.
Filtering Out Non-Visual Elements
A primary reason for separating the trees is that a one-to-one
mapping between HTML and visual output is inefficient and unnecessary.
Blink inspects the ComputedStyle of a DOM node before
generating a LayoutObject.
If an element has the CSS property display: none, or if
it is a naturally invisible tag such as <script>,
<meta>, or <head>, Blink simply
skips creating a LayoutObject for it. The element remains
in the DOM tree for JavaScript access, but it is entirely excluded from
the Layout tree. However, elements styled with
visibility: hidden do receive a LayoutObject
because they are merely invisible, meaning they still occupy physical
space in the page's geometry.
Handling Pseudo-Elements and Anonymous Boxes
Just as the DOM has nodes that do not appear in the Layout tree, the Layout tree contains objects that do not exist in the DOM.
CSS pseudo-elements like ::before and
::after generate LayoutObject nodes in the
Layout tree so they can be rendered on screen, even though they do not
exist as standard, queryable nodes in the DOM tree.
Furthermore, Blink enforces strict structural rules in the Layout
tree to simplify geometry math. For example, a block container in the
Layout tree can only contain either all inline children or all
block-level children—never a mix of both. If a developer writes HTML
that mixes raw inline text alongside a block-level
<div>, Blink maintains the separation of trees by
automatically inserting "anonymous" LayoutObject wrapper
boxes into the Layout tree. This keeps the layout math consistent
without altering the developer's actual DOM structure.
LayoutNG and the Fragment Tree
In recent years, Chromium upgraded Blink with a modern architecture
called LayoutNG, which takes tree separation a step further. Previously,
the LayoutObject held both the input data for layout and
the resulting geometric output, making the tree mutable during rendering
and prone to performance bottlenecks.
With LayoutNG, the Layout tree acts strictly as a read-only input. When Blink calculates the geometry of the page, it traverses the Layout tree and generates a completely separate, immutable structure called the Fragment Tree. This modern pipeline ensures a strict separation of concerns: the DOM tree manages document structure, the Layout tree maps the styled visual hierarchy, and the Fragment tree holds the final physical dimensions ready to be painted to the screen.