Stacking Contexts
A stacking context is a self-contained z-index universe: elements inside it stack against siblings within the same context, and the whole context stacks as one unit against outside elements.
Definition
A stacking context is created by root elements, positioned elements with z-index other than auto, flex and grid children with z-index, fixed and sticky positioning, opacity below 1, transforms, filters, will-change, and containment. Descendants of one context never interleave with content of a sibling context regardless of z-index values.
Context and scope
Debugging z-index battles: modals behind sticky headers, tooltips clipped by transformed parents, drop shadows appearing above dialogs. Also the mechanism behind why z-index: 99999 fails.
Common misconceptions
- Higher z-index always wins — z-index compares only within the same stacking context; the parent context decides the rest
- Position creates stacking contexts — position alone does not; it needs a numeric z-index, or use transform, opacity, and filters which always do
- Z-index conflicts are CSS specificity problems — they are stacking-context hierarchy problems, independent of selector specificity
Anti-patterns
- Escalating z-index values in a war between components instead of restructuring the stacking contexts
- Wrapping a portal target in a transformed, filtered, or faded parent and trapping overlays inside it
- Assuming DOM order determines paint order in the presence of positioned and composited elements
Related concepts
Related examples
Authoritative source
What it is
Painting order is not DOM order once positioning and compositing enter. The browser groups elements into stacking contexts, each with an internal order — backgrounds, negative z-index children, blocks, floats, inline, z-index auto children, positive z-index children. Contexts themselves are atomic units in their parent ordering.
How it works
Common creators: the root; position with z-index; flex and grid items with z-index; fixed and sticky; opacity under 1; transform, filter, backdrop-filter; will-change on those properties; isolation: isolate as the explicit opt-in. A child z-index of one million cannot escape its parent context that itself sits at z-index 1.
When to care
Overlay systems, modals, tooltips, sticky headers, and third-party widget embedding. Design the context hierarchy deliberately: an isolation: isolate wrapper keeps a component self-contained without magic numbers. Portals move DOM but not out of a composited parent.
Pitfalls
Debug with the layers and 3D view panels rather than guessing. Transforms added for animation silently create contexts that trap fixed-position descendants — sticky and fixed behave like absolute inside them. Filtered or faded wrappers reproduce the same trap on dropdown menus.