Under The Hood
frontend css CSS Containment Level 1-3 (all modern browsers)

CSS Containment: contain layout/paint/size Rendering Bails

Last updated
Prerequisites:
CSS layout and paint concepts
Understanding of style recalc and reflow
  • css
  • containment
  • contain
  • layout
  • paint
  • performance
  • rendering

Read at your depth

The practical view

The contain property tells the browser a subtree is independent: contain: layout makes the element independent for layout (floats/positioning inside can't leak out); contain: paint clips painting to the element's box (overflow is clipped and paint can't bleed outside); contain: size makes the element's size independent of its contents (you must size it yourself); contain: content = layout + paint; contain: strict = all three. Use contain: content on widgets whose size is fixed and whose internal changes shouldn't affect the page, to get big rendering wins: the browser skips layout/paint work outside the container.

The same idea in other frameworks

react equivalent
Virtualized React lists wrap items in contain: content so item updates don't re-layout the whole page.

Legacy vs modern

Full-page reflow on widget change vs contained widget

Without containment, updating a widget's internals can invalidate layout far beyond it; contain: content scopes the invalidation to the widget's boundary.

before → after
Uncontained widget
.widget { /* ❌ OLD: no containment — internal changes can re-layout the whole page */ }
Contained widget
.widget { contain: content; } /* ✅ NEW: layout+paint scoped to the widget boundary */

Interview gotchas

Context

Interviewers want the precise semantics of each containment kind — most people know 'it's for performance' but cannot say what each one does to layout, painting, and sizing.

The mechanical answer

contain: layout establishes the element as an independent formatting context and layout root: internal layout cannot affect elements outside (floats can't escape, and the element's layout is computed independently), so the engine can skip re-layout of ancestors when the subtree changes. contain: paint clips all painting to the element's padding box, and descendants cannot paint outside it; it also creates a stacking context and a containing block for absolutely-positioned descendants. contain: size makes the element's size depend only on its own specified dimensions (width/height or aspect-ratio), ignoring content size entirely — content is laid out within the given box and may overflow. contain: content = layout + paint; contain: strict = layout + paint + size.

Trap

The naive answer is 'contain just makes things faster'. Each keyword changes behavior: size containment can collapse an element whose content grows (if you forget to size it), and paint containment silently clips overflowing content such as dropdowns or tooltips. Another trap: thinking contain: content includes size — it does not, so content that would grow the box still affects the element's own sizing and therefore ancestors. Candidates who can enumerate the three kinds and their side effects show real depth.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.