What Happens When You Load a Page?
Clicking a link feels instant, but behind the scenes your browser streams bytes, builds trees, and paints pixels - all in a fraction of a second. Here’s what really happens when you load a web page.
Thu Oct 16 2025 • 9 min read
You click a link, see a loading bar flicker, and within seconds - a fully built page appears. It feels automatic, like the web just arrives. But in reality, that single action sets off one of the most complex processes your device ever performs: turning text files from a distant server into an interactive, animated interface.
Your browser doesn’t just “open” a page. It constructs one - piece by piece, byte by byte.
Making the Request
When you type a URL or click a link, your browser first figures out where to go. It performs a DNS lookup to resolve the domain, sets up a TCP (Transmission Control Protocol) connection, and sends an HTTP request asking for a resource - usually an HTML file.
Curious what happens before this step? See What Happens When You Type a URL — a closer look at the DNS, handshakes, and setup that lead to this moment. The server responds with chunks of text data - the raw HTML that defines the structure of the page. And here’s the clever part: the browser doesn’t wait for the whole file before acting. It starts parsing the moment the first bytes arrive.
That’s what makes the web feel fast - HTML is a streaming language.
Parsing the Stream
Browsers treat HTML like a flowing story. As bytes arrive, the HTML parser begins reading them character by character, creating tokens - start tags, end tags, text nodes, and comments.
For example:
<body>
<h1>Hello</h1>
<p>World</p>
</body>
becomes a series of tokens:
start tag <body>
start tag <h1>
text "Hello"
end tag </h1>
start tag <p>
text "World"
end tag </p>
end tag </body>
Each token is then turned into a node and placed in a tree structure known as the DOM - the Document Object Model.
Think of the DOM as a living map of the page, where every element, from <div> to <img>, becomes a node the browser can later style, script, and render.
The DOM
The DOM (Document Object Model) is your page’s blueprint. It tells the browser what exists, in what order, and how elements nest inside each other.
Example tree:
Document
└── html
├── head
└── body
├── h1 ("Hello")
└── p ("World")
But parsing HTML isn’t linear forever. Sometimes the browser has to stop and wait - and that’s where scripts come in.
Scripts Can Pause Everything
When the parser encounters a <script> tag, it often pauses to execute that script before continuing.
Why? Because JavaScript can modify the DOM structure - even elements the browser hasn’t parsed yet.
<script>
document.write('<p>Inserted while parsing</p>');
</script>
If the browser kept parsing while this ran, the final DOM could be out of sync.
To avoid that, HTML parsing stops, executes the script, updates the DOM if necessary, then resumes.
Unless the script is marked with defer or async, nothing else proceeds.
That’s why script placement and loading attributes matter so much for performance.
Speculative Parsing and the Preload Scanner
Even while the main parser pauses for a script, another hidden engine keeps moving forward - the preload scanner. Its job is to look ahead in the HTML stream and discover resources you’ll soon need: images, stylesheets, fonts, and external scripts.
The scanner runs speculatively - it can’t build the DOM, but it can read tags and start fetching assets early. That means while JavaScript executes, your next images or CSS files are already downloading.
This background race is one reason pages can still load quickly even when scripts block rendering. The browser never truly stops working; it just rearranges priorities.
Render-Blocking vs Non-Blocking Resources
Not every file you reference affects rendering the same way.
- Render-blocking resources halt the page until they’re loaded and parsed. These include CSS and synchronous
<script>tags. - Non-blocking resources - like
asyncordeferscripts, or lazy-loaded images - let the browser continue building and painting.
Every asset type travels a different route through the pipeline. CSS must arrive early because layout depends on it. JavaScript can wait unless it changes initial content. Images, fonts, and analytics should almost never block the first paint.
When you know what blocks rendering, you can intentionally design your critical path - the minimal set of assets required to show something meaningful on screen.
Building the CSSOM
While the HTML parser builds the DOM, the browser is also downloading and parsing any linked CSS.
From every stylesheet, it builds another structure - the CSS Object Model, or CSSOM. It maps which rules apply to which selectors, inheritance, and computed values.
Together, the DOM (structure) and CSSOM (appearance) form the Render Tree - a specialized view that tells the browser exactly which elements need to be drawn and how they should look.
DOM + CSSOM → Render Tree
Layout
Once the Render Tree is built, the browser performs layout (also called “reflow”). This is where it calculates every element’s position, size, and stacking order.
It takes into account things like:
- box dimensions and margins
- relative and absolute positioning
- viewport size and zoom level
Even small CSS changes - like toggling display: none - can trigger reflows that ripple through the layout.
That’s why performance-minded developers talk so much about avoiding layout thrashing.
Painting, Layers, and the GPU Pipeline
After layout comes painting - the process of turning each visual node into actual pixels on your screen.
But modern browsers don’t just paint once. They break the page into layers, send them to the GPU, and let a dedicated thread - the compositor - handle what moves or fades.
- Text, backgrounds, and borders are drawn into individual layers.
- The compositor merges these layers, applying transforms, opacity, and animations.
- The GPU rasterizes them into textures and displays them at high frame rates.
Hardware acceleration means that effects like transform, opacity, and filter can run independently of layout, keeping animations smooth even while scripts execute.
When you scroll a page or drag a modal, you’re watching the compositor redraw only what’s visible - a real-time collaboration between CPU and GPU.
Optimization Behind the Scenes
Modern browsers process many tasks at the same time. Even while the HTML parser runs, a preload scanner looks ahead for external assets - images, CSS, scripts - and starts fetching them early.
Meanwhile:
- Scripts with
asyncload in parallel. - Stylesheets are cached.
- The GPU prepares textures for animations.
All of this happens before the first full paint, often within 200–400 ms on a fast connection.
This overlapping work is what makes pages feel responsive even though so much is happening behind the curtain.
The Critical Rendering Path
All these stages - parsing, styling, layout, painting - form what’s called the Critical Rendering Path. It’s the minimal sequence of steps required to display something on screen.
Simplified, it looks like this:
HTML → DOM → Render Tree → Layout → Paint → Composite
Every optimization guide you’ve read - minifying CSS, inlining critical styles, deferring JS - aims to shorten this path.
Core Web Vitals and Real Performance
All these internal browser steps eventually show up as measurable numbers - the ones that define how fast your page feels.
- Largest Contentful Paint (LCP): the moment your main content finishes rendering. It depends on layout, paint, and image loading.
- Cumulative Layout Shift (CLS): how much the page jumps around while elements load. It tracks layout recalculations.
- First Input Delay (FID): the gap between a user action and when the browser can respond, usually blocked by long scripts.
These metrics are direct reflections of the browser’s rendering timeline. Optimizing them isn’t guesswork - it’s about working with the rendering engine: fewer blocking scripts, smaller images, and stable layout flow.
Caching and Reuse
After that first load, the browser becomes more efficient.
It stores static files like CSS, JS, and images in its HTTP cache, guided by headers like Cache-Control and ETag.
Next time you visit:
- Only changed files are fetched.
- The DOM still re-parses, but resources load from cache instantly.
- Layout and paint happen faster since style calculations are already optimized.
That’s why reloads feel nearly instant - your browser isn’t downloading everything again; it’s reassembling from local memory.
What Happens After Load
The work doesn’t end once the page appears. Every time you interact - typing, scrolling, resizing - the browser updates parts of the layout or paint.
Two common updates:
- Reflow (Layout Recalculation): triggered when dimensions or structure change. Adding a new element or changing width forces recalculation.
- Repaint: triggered when visual properties (like color or shadow) change but geometry stays the same.
Efficient web apps batch these changes, avoiding repeated reflows that block the main thread. Small choices like modifying classes instead of inline styles, or using CSS transitions instead of JS loops, help keep motion fluid.
See It in Action: DevTools Timeline
You can watch this entire process live in your browser:
- Open any site (try vayce.app).
- Open DevTools → Performance.
- Click “Record” and reload the page.
- You’ll see color-coded bars:
- Blue: Loading / Networking
- Purple: Scripting / Parsing
- Green: Painting / Compositing
That timeline shows exactly how your browser converts text into pixels, frame by frame.
Why It Matters
Understanding how a page loads changes how you build one.
- Keep it simple. Every dependency and script adds work to the parser.
- Use async/defer wisely. Let the browser keep building while your scripts load.
- Inline only what’s critical. Help the first paint happen faster.
- Batch DOM changes. Avoid multiple reflows.
- Trust the browser. It’s better at parallelizing than any human optimization guess.
When you see your site as a collaboration with the browser - not a fight against it - everything gets faster.