Main Thread Work.
Total main thread activity — parsing, compiling, painting. Keep under 4s
What does this check test?
This check measures the total time spent on the browser's main thread during page load, encompassing all categories of work: JavaScript evaluation, style calculations, layout, paint, compositing, HTML parsing, garbage collection, and other browser tasks. Lighthouse flags pages where total main thread work exceeds 4 seconds. Unlike JS Execution Time which only measures JavaScript, this metric captures the full picture of main thread utilization including the cascade effects of JavaScript on layout and painting.
Why does it matter?
The main thread is the single most critical bottleneck in browser performance — it handles JavaScript execution, DOM/CSSOM construction, layout computation, painting, and user input processing. When any of these tasks takes too long, the browser cannot respond to user interactions. High main-thread work results in poor TBT, delayed TTI, and input lag that users perceive as the site being slow or broken. Understanding the breakdown of main-thread work (how much is script vs. layout vs. paint) is essential for targeted optimization — reducing JavaScript alone does not help if excessive layout thrashing is the real problem.
Who is affected?
Sites with complex layouts (many DOM elements, deeply nested structures), heavy use of CSS animations and transitions, frequent DOM manipulation (infinite scroll, real-time updates), and large component trees that trigger cascading layout recalculations are most affected. Dashboards, data tables, social media feeds, and interactive web applications typically have the highest main-thread utilization.
Where does this apply?
Chrome DevTools Performance panel provides a complete breakdown of main-thread work by category in the Summary tab. The Main thread flame chart shows a timeline of all tasks. Key categories: Script (JS execution), Rendering (style calculation + layout), Painting (paint + compositing), System (browser internal tasks), and Idle (time available for user input). Focus optimization efforts on the largest category first.
How to fix it
// Bad — triggers layout on every iteration
elements.forEach(el => {
const height = el.offsetHeight; // read (forces layout)
el.style.height = height + 10 + 'px'; // write
});
// Good — batch reads, then writes
const heights = elements.map(el => el.offsetHeight);
requestAnimationFrame(() => {
elements.forEach((el, i) => {
el.style.height = heights[i] + 10 + 'px';
});
}); section {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
} References
- Minimize main thread work — Chrome Developers
- Rendering Performance — web.dev
- content-visibility — MDN
- Avoid large, complex layouts — web.dev
AppVet checks Main Thread Work automatically
Run a free performance scan and get a full report with actionable fixes, including a Fix with AI prompt you can paste into any coding tool.
Run Audit