How Browsers Render a Web Page
From HTML bytes to pixels on the screen
Rendering Is The Real Frontend Runtime
When we talk about frontend development, we usually talk about frameworks, components, state management, and APIs. We talk about React renders, re-renders, hooks, and performance optimizations inside JavaScript.
But long before any of that matters, the browser is already doing its most important work.
Rendering is the browser’s runtime.
Every piece of UI you ship — every button, animation, layout shift, and loading state — ultimately depends on how efficiently the browser can turn bytes into pixels.
If rendering is slow or inefficient, no framework can save the experience.
What makes rendering tricky is that most of it is invisible. There are no stack traces when layout recalculates too often. There are no console errors when painting becomes expensive. The UI just starts to feel off — slightly janky, delayed, or unpredictable.
Understanding how browsers render a web page gives you a mental model for these issues. It explains why certain CSS changes cause unexpected layout shifts, why reading layout values at the wrong time hurts performance, and why some animations feel smooth while others never do — even when they look similar in code.
In this article, we’ll walk through how a browser renders a web page from start to finish. Not from a specification or interview perspective, but from the POV of a frontend engineer who wants to build UIs that stay responsive, predictable, and fast in real-world conditions.
Once you understand this pipeline, frontend performance stops feeling like guesswork — and starts feeling like engineering.
Step 1: Receiving and Parsing HTML
Rendering begins the moment the browser receives the first bytes of HTML.
The browser does not wait for the full document to download. It starts parsing immediately, converting raw HTML text into a structured representation called the DOM (Document Object Model).
Each HTML element becomes a node in the tree. Parent-child relationships are established. Attributes are read. The structure of your page starts to exist in memory.
At this stage, the browser understands what elements exist — but not how they look.
This is why malformed or deeply nested HTML can already slow things down before any styling or scripting begins.
Step 2: Discovering External Resources
While parsing HTML, the browser encounters references to other resources:
CSS files
JavaScript files
fonts
images
Each of these may trigger additional network requests.
This discovery phase matters because some resources block rendering. For example, CSS must be loaded before the browser can safely paint the page. JavaScript, depending on how it’s loaded, can pause parsing entirely.
Frontend performance is heavily influenced by when these resources are discovered, not just how big they are.
Step 3: Parsing CSS and Building the CSSOM
Once CSS is downloaded, the browser parses it into another tree-like structure called the CSSOM (CSS Object Model).
The CSSOM describes:
which styles apply to which elements
how selectors cascade and override each other
how inheritance flows through the DOM
Unlike JavaScript, CSS parsing is blocking for rendering. The browser can’t paint content until it understands, how that content should be styled.
This is why large, complex stylesheets or expensive selectors can delay the first paint.
Step 4: Creating the Render Tree
At this point, the browser combines the DOM and the CSSOM into something called the render tree.
The render tree contains only what is actually visible on the page:
elements styled with
display: noneare excludedpseudo-elements may be included
text nodes are represented with styling information
This tree answers a very specific question:
“What exactly needs to be painted on the screen?”
Understanding this explains why some DOM changes have no visual impact — and why others are expensive.
Step 5: Layout (Calculating Sizes and Positions)
Layout is where the browser calculates:
element sizes
positions
spacing
alignment
This step depends heavily on:
CSS layout models (block, flexbox, grid)
viewport size
font metrics
dynamic content
Layout is one of the most expensive parts of rendering.
Any change that affects geometry — width, height, padding, font size — can force the browser to recalculate layout for part or all of the page.
This is why layout thrashing and unnecessary reflows hurt performance so much.
Step 6: Painting Pixels
Once layout is complete, the browser knows where everything goes.
Now it needs to actually draw pixels.
Painting involves:
drawing backgrounds
borders
text
shadows
images
Each visual detail is painted into layers. Complex visual effects (like shadows and gradients) increase paint cost.
Painting does not change the layout — it only affects how things look. But it can still be expensive, especially on low-end devices.
Step 7: Compositing Layers
Modern browsers optimize rendering by separating content into layers and compositing them together.
This allows:
smooth animations
scrolling without repainting everything
GPU acceleration for certain properties
Properties like transform and opacity are powerful because they often avoid layout and paint entirely, jumping straight into compositing.
This is why some animations feel smooth and others feel janky — they trigger different parts of the rendering pipeline.
Where JavaScript Fits Into All Of This
JavaScript doesn’t exist outside the rendering pipeline.
It interacts with it constantly:
reading layout values can force layout
writing styles can trigger repaint
heavy JS blocks rendering entirely
The browser can only render when JavaScript yields control. This is where the event loop and rendering pipeline intersect.
Understanding rendering explains why:
batching DOM updates matters
reading layout after writing styles is expensive
some “small” JS changes cause big performance regressions
Why This Matters More in Real-World Apps
On modern laptops, many rendering problems are masked by fast hardware.
On:
low-end phones
Smart TVs
embedded browsers
older devices
…the rendering pipeline becomes much less forgiving.
Small inefficiencies stack up. Layout recalculations become visible. Paint cost adds up. UI responsiveness suffers.
This is why understanding how browsers render pages isn’t optional if you care about real users.
Conclusion: Rendering is The Hidden Cost of Frontend Code
Browsers don’t magically “show UI.”
The parse, calculate, paint, and compose — every time something changes.
Once you understand this pipeline, frontend performance becomes predictable instead of mysterious. You start writing code that works with the browser, not against it.
Frontend engineering isn’t just about writing code that runs.
It’s about writing code that renders well.
If this article helped you, consider subscribing to Frontend Engineering Weekly.
I’ll be sharing:
Practical frontend lessons
Real-world engineering insights
Web, Smart TV, and modern UI topics
One article every week
No fluff. Just real engineering.
If you found this content valuable, please hit a like❤️.
If you have any questions or suggestions, please leave a comment.
Follow me on LinkedIn and DEV.to to stay updated.
Checkout my Website and GitHub for collaboration.
I hope you have a great day and a productive week!
Regards,
Aryan











This is a great read. Really makes you realize that when UI feels slow or janky, it’s often the browser’s rendering work—not the framework. “Rendering is the real runtime” is such a solid takeaway.
Great read. Perfect explanation!👏🏼