The rendering pipeline
The render tree
Distinguish the document tree from the boxes that participate in visual rendering.
The DOM describes the document. Rendering needs something different: the styled boxes that can appear on screen. The two are not the same list.
Not every DOM node creates a box. An element with display: none stays in the DOM, you can still find it with querySelector, but it takes part in neither layout nor paint. Visually, it’s as if it weren’t there.
The reverse happens too. ::before and ::after create visual content that has no DOM node at all:
.price::before {
content: '€';
}
There’s a box with a euro sign on screen, and nothing in the DOM tree that corresponds to it.
The render tree
You’ll often hear this structure called the render tree: document content combined with computed styles, containing only what renders. It’s a useful mental model.
Be careful with it though. Real engines use several internal structures with different names, and they change over time. Don’t rely on one literal universal tree. Rely on the idea: rendering works on styled boxes, not on DOM nodes.
display: none vs visibility: hidden
The two ways of hiding an element behave differently in the render tree, and the difference tells you a lot.
display: none removes the box. Layout doesn’t know about it, so the neighbors close the gap.
visibility: hidden keeps the box. Layout reserves its space and paint skips drawing it. The neighbors stay where they were.
Let’s check it in the Elements panel. Select an item in any list and add display: none in the Styles pane. The items below jump up. Change it to visibility: hidden and they move back down, leaving an empty space.
There’s a cost angle too. Toggling display forces layout, because geometry changes. Toggling visibility usually needs only paint.
Try this on your own project: for both properties, predict whether the hidden element affects layout, paint, both, or neither. Then check your prediction in DevTools.
Lesson completed