Stacking Context
Overview
The z-index property controls the Z-axis (depth) of elements, determining what overlaps what. However, z-index is notoriously misunderstood. Setting z-index: 999999 on a button doesn't guarantee it will sit on top of everything. z-index only works inside a 'Stacking Context'. If a parent element creates a Stacking Context, all of its children are trapped inside it. A child with z-index: 999 inside a parent with z-index: 1 will ALWAYS render below a sibling parent with z-index: 2.
Syntax
/* 1. Stacking Contexts ONLY apply to positioned elements! */
.box {
position: relative; /* or absolute, fixed, sticky */
z-index: 10;
}
/* 2. Modern properties that FORCE a new Stacking Context (even without position) */
.modal-wrapper {
opacity: 0.9; /* Creates a stacking context! */
transform: scale(1); /* Creates a stacking context! */
filter: blur(2px); /* Creates a stacking context! */
}Common Pitfalls
- Trying to use
z-indexon aposition: static(default) element. The browser will completely ignore it. You must addposition: relative(or absolute/fixed) forz-indexto activate. - The Z-Index War: Just arbitrarily adding
9999to everything. This creates an unmaintainable nightmare. Use a structured z-index scale (e.g.,10for dropdowns,40for navbars,50for modals).
Interview Questions
z-index: 9999 be stuck hiding underneath a navbar with z-index: 10?Because the modal is nested inside a parent <section> that has position: relative; z-index: 1;. The modal is trapped in its parent's stacking context (Layer 1). The navbar is on Layer 10. Layer 10 will always crush Layer 1, regardless of what the children inside Layer 1 have set.
Real-World Example
Managing Z-index variables at an enterprise level to prevent wars.
:root {
--z-negative: -1;
--z-elevated: 1;
--z-dropdown: 10;
--z-sticky: 20;
--z-fixed-nav: 30;
--z-modal-backdrop: 40;
--z-modal: 50;
--z-popover: 60;
}Check Your Knowledge
Test your understanding of Stacking Context with these quick questions.