Stacking Contexts & Z-Index
15 min read
Z-IndexStacking Contextpositionopacitytransformisolation
Why z-index: 9999 Sometimes Doesn't Work
Z-index is one of the most misunderstood properties in CSS. The problem is that z-index doesn't create a single global layering system — it creates stacking contexts.
What Creates a Stacking Context?
| Property | Value | Creates Context? |
|---|---|---|
position + z-index | relative/absolute/fixed + any z-index value | ✅ Yes |
opacity | Any value less than 1 | ✅ Yes |
transform | Any value (even translateZ(0)) | ✅ Yes |
filter | Any value | ✅ Yes |
isolation | isolate | ✅ Yes |
will-change | transform, opacity, etc. | ✅ Yes |
position: fixed/sticky | Always | ✅ Yes |
mix-blend-mode | Any value except normal | ✅ Yes |
contain | layout, paint, or strict | ✅ Yes |
The Key Rule
A child element can never appear above or below its parent's stacking context siblings. Think of stacking contexts as sealed envelopes — you can reorder cards inside an envelope, but the envelope's position is fixed relative to other envelopes.
Z-Index Strategy
Instead of random numbers, use a token system:
:root {
--z-dropdown: 100;
--z-sticky: 200;
--z-modal-backdrop: 300;
--z-modal: 400;
--z-toast: 500;
--z-tooltip: 600;
}