DEV Community

Cover image for Understanding the Browser Rendering Pipeline: DOM, CSSOM, Layout, Paint, Compositing & Layout Thrashing
koushikmaya
koushikmaya

Posted on

Understanding the Browser Rendering Pipeline: DOM, CSSOM, Layout, Paint, Compositing & Layout Thrashing

Understanding the Browser Rendering Pipeline: From DOM to Pixels ๐Ÿš€

A beginner-friendly look at DOM, CSSOM, Render Tree, Layout, Paint, Compositing, Critical Rendering Path, and Layout Thrashing.

Introduction

While working on my Week 2 frontend tasks in my training, I wanted to understand what actually happens inside the browser when we load a webpage.
I had heard terms like DOM, CSSOM, reflow, repaint, and compositing, but I didn't fully understand how they were connected.
So I decided to learn the browser rendering pipeline and use Chrome DevTools Performance to see some of these concepts in practice.

This post covers what I learned and the small experiment I performed on layout thrashing.

๐Ÿ“Œ What I Learned

In this learning session, I covered:

  • DOM Construction
  • CSSOM Construction
  • Render Tree
  • Style Calculation
  • Layout / Reflow
  • Paint / Repaint
  • Compositing
  • Critical Rendering Path
  • Layout Thrashing
  • Batching DOM Reads and Writes

- Chrome DevTools Performance

๐Ÿ”„ Browser Rendering Pipeline

At a high level, the browser goes through something like this:

HTML
  โ†“
DOM
  โ†“
CSS
  โ†“
CSSOM
  โ†“
Style Calculation
  โ†“
Render Tree
  โ†“
Layout
  โ†“
Paint
  โ†“
Compositing
  โ†“
Screen
Enter fullscreen mode Exit fullscreen mode

Let's understand each stage.

Let's understand each stage.

1๏ธโƒฃ DOM Construction

DOM stands for Document Object Model.
When the browser receives HTML, it parses it and creates a tree-like structure.
For example:

<body>
    <h1>Hello</h1>
    <p>Welcome</p>
</body>
Enter fullscreen mode Exit fullscreen mode

The browser creates something conceptually like:

Document
โ””โ”€โ”€ html
    โ””โ”€โ”€ body
        โ”œโ”€โ”€ h1
        โ””โ”€โ”€ p
Enter fullscreen mode Exit fullscreen mode

This is the DOM tree.

Simple way to remember

DOM = What elements exist?

2๏ธโƒฃ CSSOM Construction

CSSOM stands for CSS Object Model.
The browser also parses CSS and creates a representation of the CSS rules.
For example:

h1 {
    color: blue;
    font-size: 32px;
}
p {
    color: gray;
}
Enter fullscreen mode Exit fullscreen mode

The CSSOM helps the browser understand how the elements should be styled.

Simple way to remember

DOM   โ†’ What exists?
CSSOM โ†’ How should it look?
Enter fullscreen mode Exit fullscreen mode

3๏ธโƒฃ Style Calculation

Now the browser needs to figure out which styles actually apply to each element.
It considers things such as:

  • CSS selectors
  • Cascade
  • Specificity
  • Inheritance
  • Browser default styles
  • Media queries
  • CSS variables For example:
p {
    color: red;
}
.article p {
    color: blue;
}
Enter fullscreen mode Exit fullscreen mode

4๏ธโƒฃ Render Tree

The browser combines the DOM and CSSOM to determine what actually needs to be rendered.

DOM + CSSOM
     โ†“
Style Calculation
     โ†“
Render Tree
Enter fullscreen mode Exit fullscreen mode

The Render Tree isn't exactly the same as the DOM.
For example:

.hidden {
    display: none;
}
Enter fullscreen mode Exit fullscreen mode

The element still exists in the DOM, but it doesn't participate in the normal rendered layout.

Simple way to remember

Render Tree = What actually participates in rendering?

5๏ธโƒฃ Layout / Reflow

Once the browser knows what needs to be rendered, it needs to calculate the size and position of the elements.
This is the Layout stage.
It calculates things like:

  • Width
  • Height
  • Position
  • Margin
  • Padding
  • Text positioning For example:
.card {
    width: 300px;
    height: 200px;
}
Enter fullscreen mode Exit fullscreen mode

The browser needs to calculate where the card is and how much space it occupies.

Simple way to remember

Layout = Where is everything and how big is it?

Layout is also commonly referred to as reflow.

6๏ธโƒฃ Paint / Repaint

After calculating the layout, the browser needs to draw the page.
This is the Paint stage.
Paint deals with things such as:

  • Text
  • Backgrounds
  • Borders
  • Images
  • Shadows
  • Gradients For example:
.card {
    background: white;
    border: 1px solid #ddd;
    box-shadow: 0 4px 10px gray;
}
Enter fullscreen mode Exit fullscreen mode

These visual details need to be painted.

Simple way to remember

Paint = Draw what the user should see.

If something visual changes, the browser may need to paint that area again. This is commonly called a repaint.

7๏ธโƒฃ Compositing

After painting, the browser may have different painted surfaces or layers that need to be combined.
That's where Compositing comes in.

Layer 1
   +
Layer 2
   +
Layer 3
   โ†“
Compositing
   โ†“
Screen
Enter fullscreen mode Exit fullscreen mode

Properties such as:

transform
opacity
Enter fullscreen mode Exit fullscreen mode

can often be handled efficiently by the compositor.
This is one reason these properties are commonly used for animations.
For example:

.box {
    transform: translateX(100px);
}
Enter fullscreen mode Exit fullscreen mode

8๏ธโƒฃ Critical Rendering Path

Now we can put everything together.
The simplified Critical Rendering Path looks like this:

HTML
  โ†“
DOM

CSS
  โ†“
CSSOM

DOM + CSSOM
  โ†“
Style Calculation
  โ†“
Render Tree
  โ†“
Layout
  โ†“
Paint
  โ†“
Compositing
  โ†“
Screen
Enter fullscreen mode Exit fullscreen mode

JavaScript can modify the DOM or CSS, which may cause parts of this process to run again.

This is where frontend performance becomes important.

๐Ÿงช Practical Experiment With Chrome DevTools

Learning the theory was useful, but I wanted to actually see what was happening.
So I used my Week 2 responsive landing page and opened:

Chrome DevTools
โ†’ Performance
Enter fullscreen mode Exit fullscreen mode

I recorded the page load and inspected the Main thread.
I found rendering-related activities such as:

Recalculate Style
Layout
Paint
Composite / Commit
Enter fullscreen mode Exit fullscreen mode

This helped me connect the theory with what the browser was actually doing.
Instead of just reading:

"The browser performs layout and paint."

I could actually see rendering activity in DevTools.

๐Ÿ”ฅ Layout Thrashing Experiment

The most interesting part of the experiment was layout thrashing.
I created a simple page with multiple boxes and used JavaScript to change their height and immediately read their height.

for (const box of boxes) {
    box.style.height = "100px";
    console.log(box.offsetHeight);
}
Enter fullscreen mode Exit fullscreen mode

Here:

box.style.height = "100px";
Enter fullscreen mode Exit fullscreen mode

is a write because I'm changing the style.
And:

box.offsetHeight
Enter fullscreen mode Exit fullscreen mode

is a layout read because I'm asking the browser for the current height.
So the pattern becomes:

WRITE
  โ†“
READ
  โ†“
WRITE
  โ†“
READ
Enter fullscreen mode Exit fullscreen mode

When layout has been invalidated, reading layout information such as offsetHeight can require the browser to synchronously update layout.

Doing this repeatedly can lead to layout thrashing.

๐Ÿค” Why Is offsetHeight Important?

Some properties require the browser to provide up-to-date layout information.
Examples include:

element.offsetWidth
element.offsetHeight
element.clientWidth
element.clientHeight
element.getBoundingClientRect()
Enter fullscreen mode Exit fullscreen mode

If we've just changed something that affects layout and then immediately request one of these values, the browser may need to perform layout work before returning the result.

โŒ The Problem: Layout Thrashing

The problematic pattern is:

for (const box of boxes) {
    box.style.height = "100px";
    console.log(box.offsetHeight);
}
Enter fullscreen mode Exit fullscreen mode

Conceptually:

WRITE โ†’ READ
WRITE โ†’ READ
WRITE โ†’ READ
Enter fullscreen mode Exit fullscreen mode

This can cause unnecessary synchronous layout work

โœ… Fixing Layout Thrashing

The basic solution is to separate reads and writes.
Instead of:

WRITE โ†’ READ
WRITE โ†’ READ
WRITE โ†’ READ
Enter fullscreen mode Exit fullscreen mode

we can do:

READ
READ
READ
  โ†“
WRITE
WRITE
WRITE
Enter fullscreen mode Exit fullscreen mode

The optimized version:

// READ
for (const box of boxes) {
    console.log(box.offsetHeight);
}
// WRITE
for (const box of boxes) {
    box.style.height = "100px";
}
Enter fullscreen mode Exit fullscreen mode

This gives the browser a better opportunity to batch the rendering work.

๐Ÿ“Š Before vs After

โŒ Before

for (const box of boxes) {
    box.style.height = "100px";
    console.log(box.offsetHeight);
}
Enter fullscreen mode Exit fullscreen mode

Pattern:

WRITE โ†’ READ
WRITE โ†’ READ
WRITE โ†’ READ
Enter fullscreen mode Exit fullscreen mode

โœ… After

for (const box of boxes) {
    console.log(box.offsetHeight);
}
for (const box of boxes) {
   box.style.height = "100px";
}
Enter fullscreen mode Exit fullscreen mode

Pattern:

READ
READ
READ
   โ†“
WRITE
WRITE
WRITE
Enter fullscreen mode Exit fullscreen mode

๐Ÿ” What I Observed in DevTools

I recorded both versions using the Performance panel.
I was able to inspect:

  • JavaScript execution
  • Recalculate Style
  • Layout activity
  • Paint
  • Compositing / Commit One thing I learned during the experiment is that Chrome is heavily optimized, so we shouldn't expect to see one separate Layout event for every single operation. The important part was understanding why alternating layout writes and reads can cause synchronous rendering work. --- # ๐Ÿ’ก Key Takeaways | Concept | What I learned | | --- | --- | | DOM | Represents the structure of the HTML document. | | CSSOM | Represents the CSS rules. | | Render Tree | Determines what participates in rendering. | | Layout | Calculates the size and position of elements. | | Paint | Draws the visual appearance. | | Compositing | Combines painted surfaces/layers into the final frame. | | Layout Thrashing | Can happen when layout-affecting writes and layout reads are repeatedly mixed. | | Performance Optimization | Batch DOM/layout reads and writes when possible. | | DevTools | Performance tools are useful for understanding what the browser is actually doing instead of simply guessing. | --- # ๐ŸŽฏ What I Learned From This Before doing this experiment, I mostly thought about HTML, CSS, and JavaScript as separate parts of frontend development. Now I have a better understanding of how they connect:
HTML
 โ†“
DOM
 โ†“
CSSOM
 โ†“
Render Tree
 โ†“
Layout
 โ†“
Paint
 โ†“
Compositing
 โ†“
Screen
Enter fullscreen mode Exit fullscreen mode

I also learned that the way JavaScript interacts with the DOM can affect browser rendering performance.

The layout-thrashing experiment was especially useful because I could see how a simple operation like reading offsetHeight can become important when it is repeatedly mixed with style changes.

๐Ÿ Conclusion

This was one of those topics that made much more sense after actually experimenting with it.
Instead of only reading about reflow, repaint, and compositing, I used Chrome DevTools to observe the browser's rendering work.
The biggest lesson I took from this experiment is:

Don't just learn how the browser works. Use DevTools to see it working.

This experiment gave me a better understanding of what happens behind the scenes when the browser turns our HTML, CSS, and JavaScript into pixels.

๐Ÿ› ๏ธ Practical Work

As part of my Week 2 learning, I worked on:

  • โœ… Responsive landing page
  • โœ… Chrome DevTools Performance analysis
  • โœ… Layout, Paint and Compositing investigation
  • โœ… Layout thrashing experiment
  • โœ… Batched DOM reads and writes
  • โœ… Before/after performance comparison ## Tools Used
  • HTML
  • CSS
  • JavaScript
  • Chrome DevTools

- VS Code

๐Ÿ“š Final Note

I'm still learning frontend performance, but this experiment helped me understand that writing frontend code isn't only about making the page look correct โ€” it's also about understanding how the browser processes that code.

๐Ÿ“ My Handwritten Notes

I also made handwritten notes while learning these concepts. They helped me understand the browser rendering pipeline and remember the key points.
Here are my notes:
Handwritten notes - Browser Rendering Pipeline



Top comments (0)