How CSS works in the browser
If you're here, you probably have used CSS before. But do you know how it works under the hood? This article provides a technically detailed breakdown of how CSS works in the browser, from parsing to actually rendering it on the screen.
1. CSS Parsing #
When a browser encounters CSS, whether inline, embedded, or from external file, it must first parse it into a format that it can understand. This involves:
Byte Stream decoding #
The browser first converts the raw bytes of CSS into characters based on the specified encoding (typically UTF-8). This process involves:
- Character encoding detection
- Byte-to-character conversion
- Handling of Unicode escape sequences
Tokenization #
The character stream is converted into tokens through lexical analysis according to the CSS syntax rules defined by the CSS language specification. The CSS tokenizer recognizes several types of tokens:
- Ident tokens (identifiers like class names)
- Function tokens
- At-keywords (@media, @import, etc.)
- Hash tokens (#id)
- String tokens
- Number tokens
- Dimension tokens (numbers with units)
- Whitespace tokens
- CDC, CDO token
Example, for a simple CSS rule:
p {
font-size: 16px;
}
The browser would tokenize it into:
p
(ident-token){
({-token)font-size
(ident-token):
(colon-token)16px
(dimension-token);
(semicolon-token)}
(}-token)
At this point, the system doesn't know what's making the selector, which is property, which is value and so on...The next stage is to parse the tokens into a tree structure.
CSSOM Construction #
The tokens are then fed into the CSS Parser which outputs the CSSOM (CSS Object Model). The CSSOM is a tree structure that represents the parsed CSS, mapping styles to elements. It is structured similarly to the DOM (Document Object Model), but instead of HTML elements, it contains style rules. At this point, browser understands what part is a rule, what's a declaration, what's a selector and so on.
For example, the CSS:
p {
font-size: 16px;
}
Would generate a tree-like structure:
CSSOM
├── rule
| ├── selector (`p`)
| ├── declaration (`{ font-size: 16px; }`)
| │ ├── `font-size` : `16px`
3. Style Computation and Cascade Resolution #
Once the CSSOM is built, the browser resolves styles based on specificity, inheritance, and the cascade:
- Specificity: Determines which rule takes precedence when multiple rules apply to the same element.
- Cascade: Defines how styles are applied when multiple conflicting rules exist.
- Inheritance: Some properties (like
color
andfont
) are inherited by child elements, while others (likemargin
andpadding
) are not.
4. DOM and CSSOM Combination #
The DOM (HTML structure) and the CSSOM (styles) are combined to form the Render Tree. The render tree contains only visible elements and their computed styles.
Example:
<body>
<p>Hello World</p>
</body>
If p { display: none; }
is in the CSS, the <p>
element won't be included in the render tree.
5. Layout Computation #
Once the render tree is constructed, the browser calculates the position and size of each visible element based on:
- Box model (width, height, padding, margin, border)
- Positioning (static, relative, absolute, fixed)
- Flow, Flexbox or Grid layout mechanisms
6. Painting #
After layout computation, the browser paints elements onto the screen. This involves:
- Drawing backgrounds, borders, and text
- Applying shadows, gradients, and transforms
- Layering elements based on
z-index
Modern browsers optimize painting using GPU acceleration for certain operations like transforms and opacity changes.
7. Compositing #
For performance reasons, browsers often break rendering into layers, which can be painted independently and composited together efficiently. This helps optimize animations and complex layouts.
For example, using will-change: transform;
or position: fixed;
can trigger layer creation.
8. Repaints and Reflows #
Changes to styles can cause repaints or reflows:
- Repaint: Happens when only visual styles (like
color
) change, without affecting layout. - Reflow: Happens when layout-affecting properties (
width
,height
,position
) change, triggering a full layout recalculation.
Understanding how CSS works under the hood can help optimize performance and troubleshoot rendering issues effectively. By keeping specificity low, avoiding unnecessary reflows, and leveraging browser optimizations, you can build more efficient and smoother web experiences.