Isolate subtrees for faster rendering
CSS containment lets you promise the browser that an element’s subtree is
independent of the rest of the document, so the engine can skip work when that
subtree changes. This reference covers the contain keywords, the
content-visibility shortcut, intrinsic sizing and @container query syntax.
How it works
The contain property accepts one or more independent keywords, plus the
shorthands content (layout paint style) and strict (layout paint style size):
.widget { contain: layout paint; } /* isolate layout + paint */
.card { content-visibility: auto; /* skip off-screen render */
contain-intrinsic-size: auto 200px; }
.panel { container-type: inline-size; } /* become a query container */
@container (min-width: 40rem) {
.panel .title { font-size: 1.5rem; }
}
content-visibility: auto applies layout paint size containment and skips
rendering until the element nears the viewport; contain-intrinsic-size supplies
a placeholder size so scrolling stays stable.
What each containment type actually prevents
Understanding what each keyword isolates helps you choose the minimum needed:
layout prevents the element’s descendants from affecting the layout of
elements outside it. Floats, margins, and height changes inside a layout-contained
box cannot shift anything outside. This is the containment most useful for
independent widgets and dashboards panels.
paint restricts drawing to the element’s border box. Children cannot paint
outside it (overflow is clipped, even without overflow: hidden), and the browser
can skip repainting this box if it is outside the viewport. Note: this creates a
stacking context, which affects z-index for descendants.
size tells the browser the element’s dimensions are independent of its
children. This means the browser can skip a full layout pass of the subtree when
calculating the parent’s size — but it requires you to give the element explicit
dimensions, or it collapses to zero. inline-size only isolates the inline
(horizontal) axis, which is safe for container queries without losing block height.
style keeps CSS counters and content property values from escaping the
element’s subtree. Without style containment, a counter defined inside can bleed
into sibling elements — a subtle bug in complex list layouts.
Using content-visibility: auto for long-list performance
On pages with many cards, comment threads, or article previews, content-visibility: auto
can produce a significant rendering speedup by skipping off-screen items entirely.
The browser reserves space using contain-intrinsic-size and only fully renders
each item when it scrolls near the viewport.
.feed-item {
content-visibility: auto;
contain-intrinsic-size: auto 320px; /* estimated height */
}
The auto keyword in contain-intrinsic-size lets the browser cache the actual
rendered size after the first render, so the placeholder size becomes accurate
over time and scroll jank from incorrect estimates reduces.
Tips and notes
contain: sizecollapses an element with no explicit dimensions — preferinline-sizefor container queries.content-visibility: autois the highest-leverage value for long lists; always pair it withcontain-intrinsic-size.container-type: inline-sizeenables width-based@containerqueries without breaking block height;container-type: sizerequires a fixed height too.- Name containers with
container-nameto target a specific ancestor:@container sidebar (min-width: …). - Containment can hide overflow and break
position: fixeddescendants — test sticky/fixed children after applying it. - Paint containment creates a stacking context — descendants can no longer escape
the element’s
z-indexcontext, which can unexpectedly bury dropdowns or tooltips.