Skip to content
CSS Lab · LAB-02stacking context / compositing

What actually creates a stacking context?

A field guide to the twenty-odd declarations that quietly reorganise your paint order.

Level
ENGINEER
Read time
07 min
Experiment
Available
Type
INTERACTIVE

The question

Most developers can name two: position with z-index, and opacity. The real list is much longer, and several entries look completely harmless.

Hypothesis

Anything that forces the browser to treat a subtree as one composited group establishes a stacking context.

Method

Laboratory available

The instrument for this investigation runs in the laboratory, where the controls, the live model and the observation log share one workstation.

Enter the laboratory

Toggle declarations on the wrapper element. The bench reports whether a stacking context now exists and why.

What we observed

Three families emerge. Group semantics (opacity, filter, blend, mask) need a flattened subtree. Compositing hints (transform, will-change, backdrop-filter) promote the subtree toward its own layer. Containment (contain: paint, content-visibility) promises the browser that nothing paints outside the box, a promise only meaningful for a well-defined group.

Why it happens

DeclarationFamilyNotes
position: relative/absolute + z-index ≠ autoclassicThe one everybody knows
position: fixed / stickyclassicAlways, regardless of z-index
opacity < 1groupEven 0.999
transform ≠ nonecompositingIncluding translateZ(0)
filter / backdrop-filter ≠ nonegroupEven blur(0px)
mix-blend-mode ≠ normalgroupNeeds a backdrop group
isolation: isolategroupIts only job
will-change: <a context-creating property>compositingCreates it eagerly
contain: paint / layout / strict / contentcontainmentPaint containment implies a context
content-visibility: auto/hiddencontainmentImplies containment
flex/grid child with z-index ≠ autoclassicNo positioning required
mask / clip-path / mask-image ≠ nonegroupGroup must be flattened to clip
element in the top layer (dialog, popover)specialPainted above everything else entirely
Non-exhaustive, but covers what you will actually meet

Further research

will-change deserves a warning of its own. It is a hint with a cost: the browser may promote the element to its own compositor layer and hold the memory for as long as the declaration is there. Applying will-change: transform to everything is one of the more reliable ways to make a page slower while believing you optimised it.

References

  1. 01MDNThe stacking context, creating rules
  2. 02W3CCSS Containment Module Level 2
  3. 03MDNwill-change