At a glance the headline numbers for DOM depth
The deepest nesting level in the DOM tree.
The typical DOM tree is 18 levels deep.
Distribution & median LCP site count and median LCP at each level of DOM depth
Passing LCP by DOM depth which level passes the LCP most often
DOM depth 18. p75 23. p99 41. At the low end (11–11): LCP 1.1s. At the high end (27+): LCP 1.6s. computed
Why this matters for the Core Web Vitals, and where to start fixing it
Depth is a different problem than size. Styles inherit downwards. Toggle a class high in the tree and the browser recalculates everything below it. Layout changes also travel through ancestors, and percentage heights and flexbox make that worse. Selector matching walks the ancestor chain too, so deep trees pay more for every CSS rule.
In practice this shows up as INP. The click is fast and the JavaScript is fast, but the style and layout pass after the update is slow because the change affects too many nested levels. A flatter tree holds the same content but keeps each update local.
Chrome field data from 189,915 sites, representing millions of real page loads. How we measured.
Live queries (2) — admin only
SELECT COUNT(*) AS count,
quantile_disc(m.dom.max_depth, 0.10) AS p10,
quantile_disc(m.dom.max_depth, 0.25) AS p25,
quantile_disc(m.dom.max_depth, 0.50) AS p50,
quantile_disc(m.dom.max_depth, 0.75) AS p75,
quantile_disc(m.dom.max_depth, 0.90) AS p90,
quantile_disc(m.dom.max_depth, 0.99) AS p99
FROM sites WHERE m.dom.max_depth IS NOT NULL;
SELECT CASE WHEN m.dom.max_depth >= 11 AND m.dom.max_depth < 12 THEN 0 WHEN m.dom.max_depth >= 12 AND m.dom.max_depth < 13 THEN 1 WHEN m.dom.max_depth >= 13 AND m.dom.max_depth < 14 THEN 2 WHEN m.dom.max_depth >= 14 AND m.dom.max_depth < 15 THEN 3 WHEN m.dom.max_depth >= 15 AND m.dom.max_depth < 16 THEN 4 WHEN m.dom.max_depth >= 16 AND m.dom.max_depth < 17 THEN 5 WHEN m.dom.max_depth >= 17 AND m.dom.max_depth < 18 THEN 6 WHEN m.dom.max_depth >= 18 AND m.dom.max_depth < 19 THEN 7 WHEN m.dom.max_depth >= 19 AND m.dom.max_depth < 20 THEN 8 WHEN m.dom.max_depth >= 20 AND m.dom.max_depth < 21 THEN 9 WHEN m.dom.max_depth >= 21 AND m.dom.max_depth < 22 THEN 10 WHEN m.dom.max_depth >= 22 AND m.dom.max_depth < 23 THEN 11 WHEN m.dom.max_depth >= 23 AND m.dom.max_depth < 24 THEN 12 WHEN m.dom.max_depth >= 24 AND m.dom.max_depth < 25 THEN 13 WHEN m.dom.max_depth >= 25 AND m.dom.max_depth < 26 THEN 14 WHEN m.dom.max_depth >= 26 AND m.dom.max_depth < 27 THEN 15 WHEN m.dom.max_depth >= 27 THEN 16 END AS bucket_idx, COUNT(*) AS n,
quantile_disc(crux."desktop".lcp, 0.5) AS median,
COUNT(*) FILTER (WHERE crux."desktop".lcp IS NOT NULL AND crux."desktop".lcp <= 2500) * 1.0 / NULLIF(COUNT(*) FILTER (WHERE crux."desktop".lcp IS NOT NULL), 0) AS good_pct
FROM sites WHERE m.dom.max_depth IS NOT NULL GROUP BY bucket_idx;