This article is published in English.
From Stylesheet to Screen: Where CSS Fits in the Browser Pipeline
Follow CSS from download to pixels: how the DOM, CSSOM and render tree are built, where the cascade runs, and which style origins compete for each element.
Most developers write CSS by feel: change a property, reload, check the result. That works until a rule mysteriously refuses to apply, a page flashes unstyled content, or a "simple" style change makes scrolling stutter. Each of those problems becomes easier to reason about once you know what the browser actually does between receiving a stylesheet and drawing pixels.
This guide traces that journey at a high level. You will see how the browser turns HTML into the DOM, how stylesheets become the CSSOM, how the two combine into a render tree, where the cascade settles conflicting declarations, and which sources of styles compete for every element. It is also a common interview question, usually phrased as "how does CSS work under the hood?", and the answer below gives you a structured way to respond.
Step one: HTML becomes the DOM
When you open a URL, the browser first receives the HTML document. It parses the markup from top to bottom, and as it goes it builds the Document Object Model. The DOM is a tree that represents the whole document: each element is a node, and nodes relate to one another as parents, children and siblings, much like a family tree. Everything the HTML described now lives in this structure, and it is also what JavaScript reads and modifies.
Parsing is incremental. The browser does not wait for the whole file before it starts building nodes, which is why it can discover other resources long before the document has finished downloading.
Step two: stylesheets become the CSSOM
While parsing the HTML, the browser encounters stylesheets, whether they are linked with <link rel="stylesheet"> in the head or embedded in <style> elements, and starts fetching and parsing them too. CSS is parsed into its own tree-shaped structure, the CSS Object Model, or CSSOM. It plays the same role for styles that the DOM plays for markup.
Turning CSS into styles that can be used for an element involves more work than turning HTML into nodes. Two tasks stand out:
- Resolving conflicts. Several declarations often target the same property on the same element. The browser settles those conflicts with an algorithm called the cascade.
- Processing final values. The winning declaration may say
2em,50%orinherit, which is not yet something the layout engine can use. The browser converts these into concrete values.
Strictly speaking, the CSSOM is the parsed representation of the stylesheets, and the cascade and value computation happen when the browser calculates the style of each element. For a mental model, though, it is fine to think of it as "CSS is parsed, conflicts are resolved, values are finalised, and the result is attached to the elements".
One practical consequence: because the browser needs styles before it can render anything sensible, stylesheets in the head block rendering until they have loaded and been parsed. That is why large, slow stylesheets delay the first paint, and why keeping critical CSS small matters for performance.
Step three: DOM and CSSOM combine into the render tree
With markup parsed into the DOM and styles into the CSSOM, the browser merges the two into a render tree. The render tree contains the nodes that will actually be displayed, each paired with its computed styles. Nodes that produce no visual output, such as the contents of <head> or elements with display: none, are left out.
At this point the browser knows what to draw and how each piece is styled, but not yet where anything goes or how big it is.
Step four: layout and the visual formatting model
To turn styled nodes into positioned boxes, the browser follows what the CSS specifications call the visual formatting model. This part of the CSS specification describes how the elements of the document tree are laid out for visual media such as a laptop or phone screen. It covers the box model, block and inline formatting, floats, positioning and the other rules that determine the size and position of every box.
Once layout has computed geometry for each box, the browser paints them, filling in text, colours, borders, images and shadows, and the result finally appears on screen.
The whole pipeline at a glance
Putting the stages together gives a simple sequence from markup to pixels. Each arrow hides a significant amount of work, but the order is what matters for reasoning about bugs and performance:
HTML
↓
DOM
↓
CSS
↓
CSSOM
↓
DOM + CSSOM
↓
Render Tree
↓
Layout
↓
Paint
↓
Pixels on the Screen
Real browsers overlap these steps and add more (compositing layers, for example), and changing a style later can send the browser back to recalculate styles, redo layout or repaint, depending on the property. For a closer look at those costs, see what each CSS change costs the browser.
Why declarations conflict
The rest of this guide zooms into the first of the two CSS processing tasks: conflict resolution. The algorithm responsible is the cascade. It combines all the stylesheets that apply to a document and, whenever more than one declaration sets the same property on the same element, decides which one wins.
Conflicts are unavoidable, and not only because your own stylesheet might set color on a link in two places. Styles come from several independent sources, called origins, and all of them apply to the same elements at the same time.
Author styles
These are the declarations you and your team write: your stylesheets, <style> blocks and inline style attributes. On most sites they are by far the largest source of rules.
User styles
The person viewing the page can influence styles too. Browsers let users adjust settings such as the default font size, and some also support custom user stylesheets or extensions that inject them. These preferences are especially important for accessibility, because they let readers with low vision or reading difficulties adapt a page to their needs.
User-agent styles
Finally, the browser (the user agent) ships its own default stylesheet. That is why an unstyled <a> element appears blue and underlined, why headings are bold and larger than body text, and why <body> has a small margin. These defaults are known as user-agent styles.
When the cascade merges all three origins, the same property on the same element can easily receive several competing values, and the browser needs a deterministic way to choose.
How the cascade decides
The cascade compares conflicting declarations using a fixed sequence of criteria, moving to the next one only when the previous one results in a tie:
- Origin and importance. Where the declaration comes from, and whether it is marked
!important. - Specificity. How precisely the selector targets the element; an ID selector beats a class, which beats a type selector.
- Source order. If everything else is equal, the declaration that appears later wins.
Ranking the origins
For the first criterion, the classic order of precedence runs from highest to lowest as follows:
- User declarations marked
!important. - Author declarations marked
!important. - Normal author declarations.
- Normal user declarations.
- User-agent (browser default) declarations.
Notice what this means. Your ordinary styles override the user's ordinary preferences and the browser defaults, which is what lets you design a page at all. But !important reverses the order between users and authors: a user who truly needs a larger font or higher contrast can mark that preference as important and beat even your !important rules. The browser's own defaults sit at the bottom and only apply when nobody else says anything.
Modern CSS refines this picture. The current cascade also accounts for cascade layers (@layer), for styles set by running animations and transitions, and for user-agent !important declarations, which rank above all other important declarations. The simplified list above still captures the relationship that matters most day to day; check the MDN cascade reference linked earlier for the complete ordering.
Specificity and source order deserve their own detailed treatment, including how selector weights are compared and why !important so often causes more problems than it solves. That is covered in how the cascade picks a winner.
Why this knowledge pays off
Understanding the pipeline changes how you debug and write styles:
- Rules that do not apply are almost always cascade losses. Knowing the order of origin, specificity and source order tells you where to look instead of reaching for
!important. - Flashes of unstyled or late-styled content come from the render-blocking nature of stylesheets and from styles that arrive after the first render.
- Janky interactions often trace back to changes that force layout or paint to run again, which you can avoid once you know which stage a property affects.
- Maintainable CSS tends to be CSS with low, predictable specificity and a clear source order, which is easier for both the browser and your colleagues to process.
Wrapping up
The browser turns HTML into the DOM, stylesheets into the CSSOM, combines them into a render tree of visible, styled nodes, and then uses the visual formatting model to lay out boxes before painting them. Inside the CSS stage, the cascade is the first gatekeeper: it merges author, user and user-agent styles and resolves every conflict by origin and importance, then specificity, then source order. The next stage, turning the winning values into concrete numbers the layout engine can use, is explained in how browsers resolve CSS values before layout.