What does a browser actually do?
A browser is an execution environment, not just a document viewer. It parses HTML and CSS into trees, runs JavaScript, exposes APIs for networking and storage, and renders the result to pixels. Understanding that pipeline turns performance from guesswork into engineering.
The browser vendors ship three main engines: Blink (Chrome, Edge, Opera), Gecko (Firefox) and WebKit (Safari). They implement the same standards, so the concepts here apply everywhere even when the details differ.
Parsing HTML into the DOM
When the browser receives HTML, it parses it into the DOM: a tree of objects representing every element, attribute and piece of text. The parser is streaming, so it can start building the tree before the whole document arrives.
HTML parsing is resilient by design. A missing closing tag or a misplaced element does not stop the page; the parser recovers and keeps going. That is why malformed markup still renders, and why validating your HTML matters for predictability.
CSS and the CSSOM
Stylesheets are parsed into the CSSOM, a tree of rules. The browser then computes the final style of every element by combining the cascade, inheritance and specificity.
CSS is render-blocking: the browser will not paint until it has the styles it needs, because painting with the wrong styles would cause a visible flash. That is why a large stylesheet in the head delays the first paint, and why inlining critical CSS helps.
The render tree
The DOM and CSSOM combine into the render tree, which contains only the elements that will actually be displayed, each with its computed styles. Elements with display: none are excluded; visibility: hidden elements are included but not painted.
From here the browser knows what to draw, but not yet where.
Layout
Layout, also called reflow, computes the size and position of every box in the render tree. It walks the tree, resolving widths, heights, margins, padding and positioning, and produces a box model with exact geometry.
Layout is expensive because changes can cascade: resizing one element can move its siblings, its parent and everything below. Reading properties like offsetHeight forces the browser to ensure layout is up to date, so interleaving reads and writes triggers repeated layouts.
Paint and composite
After layout, the browser paints boxes into layers, filling in colours, text, images, borders and shadows. It then composites those layers, often on the GPU, to produce the final frame.
Some changes are cheaper than others:
- Changing a colour triggers paint.
- Changing a size triggers layout and paint.
- Changing
transformoropacitycan be handled by the compositor, skipping layout and paint entirely.
That is why animations should stick to transforms and opacity. See the CSS Animations guide and the Web Performance guide.
The critical rendering path
The path from HTML to first pixels is:
- Parse HTML into the DOM.
- Parse CSS into the CSSOM.
- Combine them into the render tree.
- Layout the boxes.
- Paint and composite the frame.
Shortening this path is the core of perceived performance: fewer blocking resources, smaller CSS, and JavaScript that does not get in the way.
<!-- fast.html -->
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin />
<style>/* critical, above-the-fold CSS */</style>
<script src="/app.js" defer></script>
preload starts important requests early, inlined critical CSS avoids a blocking round trip, and defer lets the parser finish before the script runs.
The main thread and JavaScript
The main thread runs JavaScript, layout, paint and event handling. Only one thing happens at a time, so a long task blocks input and makes the page feel frozen.
- Keep tasks short and break up expensive work.
- Move heavy computation to a Web Worker, which runs on a separate thread.
- Avoid layout thrashing by batching DOM reads and writes.
- Yield to the browser between chunks of work.
This is the same event loop you met in the JavaScript guide, now with rendering work competing for the same thread.
Storage and browser APIs
Beyond rendering, the browser provides storage and platform APIs: cookies, localStorage and sessionStorage, IndexedDB, the Cache API, service workers, WebSockets, WebRTC, the Clipboard, Notifications and more. These are what let a web page behave like an application. The PWA guide covers service workers and caching.
Best practices
- Keep the critical path short: inline critical CSS, defer scripts.
- Use
preloadfor fonts and other render-critical assets. - Animate transform and opacity, not layout properties.
- Batch DOM reads and writes to avoid layout thrashing.
- Keep JavaScript tasks short; use Web Workers for heavy work.
- Reserve space for images and embeds to avoid layout shift.
- Test in multiple engines, especially Safari and mobile.
Common mistakes
- Assuming the DOM is the HTML source.
- Blocking rendering with large stylesheets or synchronous scripts.
- Reading layout properties in a loop and forcing repeated reflows.
- Animating
widthortopand causing jank. - Running heavy computation on the main thread.
- Testing only in one browser and missing engine differences.
Where to go next
Browser internals explain why performance advice works. Put it into practice with the Web Performance guide, animate efficiently with CSS Animations, and manipulate the tree safely with DOM Manipulation. Then open DevTools and watch the rendering pipeline in the performance panel.