CSS z-index and stacking context
What is z-index?
z-index controls the stacking order of positioned elements along the z-axis (depth). Higher values appear in front of lower values.
Basic Usage
.behind {
position: relative;
z-index: 1;
}
.in-front {
position: relative;
z-index: 2; /* Appears above .behind */
}Key rule: z-index only works on elements with a position value other than static (i.e., relative, absolute, fixed, or sticky), or on flex/grid children.
What is a Stacking Context?
A stacking context is a three-dimensional conceptual container that determines how child elements are stacked. Children are isolated — their z-index only competes with siblings in the same stacking context.
What Creates a Stacking Context?
| Property/Condition | Example |
|---|---|
| Root element | <html> |
position + z-index (not auto) | position: relative; z-index: 1; |
opacity < 1 | opacity: 0.99; |
transform (any value) | transform: translateX(0); |
filter (any value) | filter: blur(0); |
will-change | will-change: transform; |
isolation: isolate | Explicitly creates a context |
position: fixed or sticky | Always creates a context |
| Flex/Grid child with z-index | z-index: 1; on flex child |
The Classic z-index Problem
<div class="parent-a" style="position: relative; z-index: 1;">
<div class="child" style="position: relative; z-index: 9999;">
I have z-index: 9999 but I'm trapped!
</div>
</div>
<div class="parent-b" style="position: relative; z-index: 2;">
I appear ABOVE child despite z-index: 2
</div>The child with z-index: 9999 can never appear above parent-b because its parent (parent-a) has a lower z-index. The child's stacking is isolated within parent-a.
isolation: isolate
isolation: isolate creates a new stacking context without side effects:
.modal-container {
isolation: isolate; /* New stacking context, clean */
}
.modal {
position: fixed;
z-index: 100;
}Best Practices
Use z-index Scale
:root {
--z-dropdown: 100;
--z-sticky: 200;
--z-overlay: 300;
--z-modal: 400;
--z-popover: 500;
--z-tooltip: 600;
--z-toast: 700;
}
.modal { z-index: var(--z-modal); }
.tooltip { z-index: var(--z-tooltip); }
.dropdown { z-index: var(--z-dropdown); }Avoid z-index Wars
/* ❌ Bad */
.header { z-index: 99999; }
/* ✅ Good — use organized scale */
.header { z-index: var(--z-sticky); }Debugging z-index
- Open browser DevTools
- Inspect the element and check its
z-index - Walk up the DOM to find parent stacking contexts
- Check if any ancestor has
opacity,transform,filter, orwill-change— these silently create stacking contexts
Important:
Most z-index issues stem from not understanding stacking contexts. Remember: a child can never escape its parent's stacking context. Use isolation: isolate to create controlled stacking contexts and organize z-index values with CSS custom properties.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.