How Do CSS ::before and ::after Generate Layout Content?
CSS pseudo-elements ::before and ::after
generate visual content by creating virtual child elements directly
inside the target element's formatting box. Rather than mutating the
HTML Document Object Model (DOM), the browser's layout engine injects
these pseudo-elements into the render tree whenever a valid
content property is declared. Once generated, they
participate in the layout pipeline identically to standard HTML
elements, following normal CSS box-model rules, formatting contexts, and
positioning schemes.
The Render Tree vs. The DOM Tree
To understand how pseudo-elements generate layout, it is necessary to distinguish between the DOM tree and the render (or formatting) tree. The DOM represents the parsed HTML document structure. When the browser constructs the render tree to compute layout geometry and paint pixels, it combines the DOM nodes with their computed CSS styles.
Pseudo-elements do not exist in the DOM, meaning JavaScript methods
like document.querySelector('::before') cannot access them
directly. Instead, the CSS engine constructs them exclusively within the
render tree. They act as the target element's first child
(::before) or last child (::after), nested
inside the element's container box.
The Critical Role of
the content Property
A pseudo-element generates a box in the layout tree if and only if
its content property is defined with a valid value other
than none or normal.
If content is missing, set to none, or
invalid, the browser suppresses box generation entirely. Setting
content: "" generates an empty box that can be sized,
colored, and positioned purely for visual layout.
.card::before {
content: "";
display: block;
width: 100%;
height: 4px;
background-color: #007acc;
}The content property accepts several types of
values:
- String literals: Text strings rendered as anonymous text boxes.
- Attribute functions:
attr(data-label)extracts attribute values directly from the parent DOM element. - Counters:
counter(section-counter)renders numerical counters for ordered lists and sections. - Asset resources:
url('icon.svg')embeds external visual assets. - Quotes:
open-quoteandclose-quoteapply language-appropriate typography quotes.
Box Generation and Flow Behavior
By default, the initial computed value of display for
pseudo-elements is inline. This means they flow naturally
with adjacent inline content and text runs. However, you can explicitly
reassign the display property to any valid layout
model.
Inline and Block Formatting
When styled with display: block, a pseudo-element breaks
onto its own line and expands across the available inline axis of the
parent container. When left as inline, it respects line
heights, baseline alignment, and horizontal margins/padding, wrapping
with the surrounding text.
Flex and Grid Containers
If the parent element uses display: flex or
display: grid, its ::before and
::after pseudo-elements become direct flex items or grid
items.
.badge-container {
display: flex;
align-items: center;
gap: 8px;
}
.badge-container::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background: #28a745;
}In this flexbox layout, the browser treats the ::before
pseudo-element as the first flex item, automatically applying flex
alignment, gap calculations, and ordering rules.
Positioning Contexts
Setting position: absolute or
position: fixed removes the pseudo-element from the normal
document flow. An absolutely positioned pseudo-element will position
itself relative to the nearest positioned ancestor (an ancestor with
position: relative, absolute,
fixed, or sticky). This pattern is commonly
used for decorative backgrounds, overlays, or custom interactive
markers.
Sizing and the CSS Box Model
Once generated, pseudo-element boxes adhere to all standard CSS box-model specifications:
- Box Sizing: Controlled by
box-sizing: border-boxorcontent-box. - Dimensions: Width, height, min/max dimensions compute according to standard layout rules.
- Margins, Borders, and Padding: Applied identically to native HTML elements.
- Stacking Contexts: Managed by
z-index,opacity,transform, and blending modes.
Because ::before and ::after generate fully
compliant render boxes without cluttering the HTML markup with
presentational <span> or <div>
tags, they serve as a core tool for cleanly separating structure from
design in modern web development.