How Does a Browser Turn Code Into a Web Page?
Every time a web page appears on your screen, a browser has already made thousands of small decisions in a fraction of a second. It has read text, built invisible structures, calculated the size of every button and paragraph, and painted millions of pixels in the correct order. None of this is visible. What you see is a finished page, arriving so quickly that the process feels instantaneous.
But it isn’t instantaneous. It’s a pipeline: a strict sequence of steps that transforms raw HTML, CSS, and JavaScript into the arrangement of colored pixels your eyes interpret as a webpage. Skip a step, and the page breaks. Slow one down, and the page stutters or freezes. Understanding this pipeline explains something that often feels mysterious: why some websites feel instant while others feel sluggish, and why a single line of poorly placed code can make a page crawl.
This is the story of what happens between the moment a server sends back a page and the moment you actually see it.
The Browser Doesn’t Read a Page. It Builds One
A common misconception is that a browser simply “displays” the code it receives, the way a projector displays a slide. It doesn’t. The HTML file that arrives from a server is just text: a sequence of characters describing headings, paragraphs, links, and images. The browser has to construct an actual internal model of the page before it can show anything at all.
That model is called the Document Object Model, or DOM. As the browser receives HTML, it breaks the text into tokens, converts those tokens into objects, and connects the objects into a tree structure that mirrors the nesting of the original tags. A paragraph inside a section becomes a child node of that section in the tree. An image inside a paragraph becomes a child of the paragraph.
Crucially, browsers do not wait for the entire HTML file to arrive before starting this work. Browsers stream-parse HTML, meaning they start building the DOM before the entire document is downloaded. This is why long pages often begin rendering their top sections before the rest of the file has even finished loading. Waiting for everything to arrive first would make every page feel slower than it needs to be.
There is one significant complication. JavaScript can interrupt this process: if the browser encounters a script tag in the middle of the HTML, it generally has to pause building the DOM, fetch and run the script, and only then continue. This is one reason developers place scripts near the bottom of a page, or mark them with attributes that let the browser keep parsing in the background.
Style Has Its Own Invisible Tree
Text structure is only half of what a browser needs. It also has to know how each element should look: its color, size, spacing, and position. That information comes from CSS, and the browser turns it into a second internal structure called the CSS Object Model, or CSSOM.
The CSSOM behaves very differently from the DOM. While the DOM is constructed incrementally, the CSSOM is not, because CSS rules can be overwritten, so the content can’t be rendered until the CSSOM is complete. A later rule in a stylesheet can override an earlier one, so the browser cannot safely apply any style until it has seen the entire stylesheet.
This has a practical consequence that shapes how the modern web is built. CSS parsing is not incremental; it is render-blocking. The browser fetches the whole stylesheet before moving on. The reasoning is simple: if styles were applied piece by piece as they loaded, elements would shift position, colors would flicker, and the page would visibly reassemble itself in front of the user. Waiting until the CSSOM is complete prevents that flash of unstyled, then re-styled, content.
This is why the placement of stylesheet links in the head of a document isn’t just convention. It’s a deliberate decision to let the browser gather all style information before it commits to showing anything at all.
Two Trees Become One
Once the browser has both the DOM and the CSSOM, it faces a new problem. The DOM describes what exists on the page. The CSSOM describes how things should look. Neither tree, by itself, tells the browser what should actually appear on screen.
To solve this, the browser merges the two into a render tree. The CSSOM and DOM trees are combined into a render tree, which is then used to compute the layout of each visible element and serves as an input to the paint process that renders the pixels to screen.
The render tree is not simply the DOM with styles attached. It’s a filtered structure that contains only what will actually be visible. If an element is hidden using display: none, it is omitted from the render tree entirely. However, elements with visibility: hidden are included in the render tree, since they still take up space even though that space stays empty.
This distinction matters more than it might seem. It explains a subtlety that trips up many people learning web design: two CSS properties that both make an element invisible can produce completely different layouts, because one removes the element from consideration entirely while the other merely makes it transparent.
Where Every Pixel Gets Its Address
With the render tree complete, the browser still doesn’t know where anything actually sits on the screen. It knows what should be visible and roughly how it should look, but not the exact coordinates, widths, and heights involved. That calculation is called layout, and it is one of the most computationally expensive parts of the entire pipeline.
During layout, sometimes called reflow, the browser calculates the exact position and size of every element in the render tree. This is a genuinely difficult problem, because elements depend on each other. A paragraph’s width might depend on its parent container. That container’s height might depend on the paragraph inside it. The browser has to resolve this web of dependencies for every visible element on the page, and it has to redo the calculation whenever something changes, whether that’s a window resize, a font loading late, or a script that alters an element’s size.
This is why developers who build interactive websites are so careful about triggering unnecessary layout recalculations. Forcing the browser to repeat this expensive process too often, especially during scrolling or animation, is one of the most common causes of a page that feels janky rather than smooth.
Turning Geometry Into Pixels
Layout tells the browser where everything belongs. Paint is the step where that geometry actually becomes visible. Paint is the process of filling in pixels with visual content like colors, images, borders, and shadows.
For a simple page, painting might be the final step. But modern web pages are rarely simple, and browsers have an additional trick for handling complexity efficiently: compositing. In some cases, content can be promoted to its own layer and composited, improving performance by painting portions of the screen on the GPU instead of the CPU, freeing up the main thread.
In practice, this means that certain elements, often ones involved in animation, transparency, or three-dimensional transforms, get pulled onto their own separate layer, rendered by the graphics processor, and then combined with everything else at the very last moment. Elements are drawn to the screen, converting boxes and styles into pixels. Some elements are promoted to their own layers, which are composited for efficient painting.
This is the technical reason a smoothly animated element can glide across a page without forcing the entire layout to be recalculated on every single frame. The browser isn’t repainting the whole page sixty times a second. It’s shifting a pre-rendered layer and letting the graphics hardware handle the rest.
Why the Order of Operations Is Not Negotiable
None of these steps can happen in a different order, and that rigidity is not a design flaw. It reflects an unavoidable dependency chain. The browser cannot calculate layout before it knows both what elements exist and how they are styled. It cannot paint before it knows where everything sits. It cannot composite before it has painted.
This ordered sequence has a name: the critical rendering path. The Critical Rendering Path is the sequence of steps the browser goes through to convert the HTML, CSS, and JavaScript into pixels on the screen. Every optimization technique in modern web development, from lazy-loading images to deferring scripts to inlining critical styles, exists because developers are trying to help the browser move through this path with as little delay as possible.
This also explains a pattern anyone who has used the web has noticed: pages with heavy, render-blocking stylesheets or scripts near the top of the document often show a blank white screen for a moment before anything appears, while well-optimized pages seem to draw content almost immediately. Both pages are running through the identical pipeline. The difference lies entirely in how much work the browser is forced to complete before it’s allowed to show the user anything at all.
What People Get Wrong About “Loading”
Many users think of a page as “loading” the way a file downloads: as a single, continuous transfer that finishes and then displays. In reality, loading, parsing, styling, laying out, painting, and compositing are distinct and overlapping processes, each with its own bottlenecks and blocking behavior.
This is also why a page can appear to have “finished loading” while still being unresponsive to clicks. The browser becomes responsive to user input once the main thread is free, and the main thread can remain busy with JavaScript execution, layout recalculation, or paint operations well after the visual content has appeared. A page that looks complete and a page that is actually ready to use are not always the same thing.
A Pipeline Built for an Impossible Deadline
The entire rendering pipeline exists to solve one persistent constraint: human perception. For motion, text, and interaction to feel smooth rather than jerky, browsers generally need to complete this entire sequence, parsing, styling, tree construction, layout, paint, and compositing, roughly sixty times every second during animation or scrolling. That leaves the browser with only about sixteen milliseconds to do all of it before the next frame is due.
Seen this way, a web page is not a static document that a browser reveals. It is a structure the browser continuously rebuilds, moment by moment, fast enough that the reconstruction itself becomes invisible. The page you’re reading right now didn’t simply appear. It was assembled, piece by piece, in less time than it takes to notice.
Frequently Asked Questions
Why does a page sometimes flash unstyled content before it looks normal?
This usually happens when the browser is forced to render before the CSSOM is fully built, often because stylesheets are loaded too late or blocked by other resources. Since CSS is render-blocking by design, a delay in receiving stylesheets can create a brief gap where content appears before its intended styling is applied.
Does every browser build the render tree in exactly the same way?
The general sequence, DOM, CSSOM, render tree, layout, paint, is shared across major browsers, but the internal engines that perform these steps differ. Chrome, Firefox, and Safari each use their own rendering engines with different optimization strategies, which is one reason the same page can occasionally render with subtle differences across browsers.
Why do developers put script tags at the bottom of a page?
Because an unmarked script tag can pause DOM construction while it downloads and executes. Placing scripts at the end, or using attributes that let them load without blocking, allows the browser to keep building the visible page instead of stalling on code that doesn’t need to run immediately.
Is compositing the same thing as painting?
No. Painting fills in the actual visual details, colors, text, borders, within layout boundaries. Compositing is a separate step where certain layers are combined by the GPU, which allows some changes, like animations, to update without repeating the more expensive layout and paint steps.