z-index
z-index
Level 4 — Display & Positioning The property that controls the 3D stacking order (the Z-axis) of elements that overlap each other.
1. Prerequisites
position: staticvsrelative— Just liketopandleft,z-indexonly works on positioned elements.
2. Term Category
Positioning Stacking Property (Universal Browser Support): z-index is a fundamental concept in this technology stack. Level 4 — Display & Positioning
3. Explanation
(1) Design Motivation — "Why did we design this?"
In standard layout, elements sit next to each other or below each other (the X and Y axes). However, the moment you use absolute, fixed, or relative positioning, or negative margins, elements can physically overlap each other.
When two elements overlap, which one goes on top? By default, the browser simply puts the element that comes last in the HTML code on top of everything else.
The W3C created z-index (referring to the 3D Z-axis) to let developers manually override this stacking order. Elements with a higher z-index number will always sit on top of elements with a lower number.
(2) Reality Metaphor
Imagine a stack of papers on a desk.
- A paper with
z-index: 1is at the bottom of the pile. - A paper with
z-index: 2is placed on top of it. - A paper with
z-index: 9999is placed on the very top of the entire pile.
(3) Code Examples
The Standard Stacking Order
.background-image {
position: absolute;
/* Send it to the back */
z-index: 1;
}
.text-overlay {
position: absolute;
/* Bring it to the front, above the image */
z-index: 2;
}
.critical-modal-popup {
position: fixed;
/* Ensure this sits on top of literally everything on the entire website */
z-index: 9999;
}
4. Common Mistakes & Pitfalls
Mistake 1: Trying to z-index a static element
The mistake: Applying z-index: 99; to a normal <div> and wondering why an image is still overlapping it.
Why it's wrong: z-index does nothing if position: static is active! If you want to use z-index, you MUST add position: relative; (or absolute/fixed) to the element first to unlock its ability to use the Z-axis.
Mistake 2: The Stacking Context Trap (Advanced)
The mistake: Giving a tooltip z-index: 9999;, but it still gets hidden behind a header that only has z-index: 2;.
Why it's wrong: Stacking is isolated inside parent containers! If a child is inside a parent that has z-index: 1, the child can never overlap a completely different element that has z-index: 2. The child is trapped inside its parent's stacking layer. You can't break out of a lower layer just by giving the child a ridiculously high number. (Think of it like folders: a file inside a folder at the bottom of the drawer can never sit on top of a folder at the top of the drawer).
Mistake 3: Applying z-index to Default position: static Elements
The mistake: Writing div { z-index: 100; } without specifying a position property.
Why it's wrong: z-index works ONLY on positioned elements (relative, absolute, fixed, sticky) or Flex/Grid child items. It is IGNORED on position: static elements.
Incorrect:
div { z-index: 999; } /* ❌ z-index is ignored on default static elements! */
Fix:
div { position: relative; z-index: 999; } /* Position relative enables z-index */
Mistake 4: Escalating to Absurd z-index Values (z-index: 99999999)
The mistake: Adding z-index: 999999 whenever an element fails to appear on top.
Why it's wrong: Absurd z-index values mean you do not understand the element's parent Stacking Context. Organize z-index using CSS custom properties or design system scale tokens.
Incorrect:
.modal { z-index: 9999999; } /* ❌ Specificity war anti-pattern! */
Fix:
/* Use CSS variables for organized z-index layer tokens: */
:root {
--z-dropdown: 1000;
--z-modal: 2000;
}
.modal { z-index: var(--z-modal); }
5. Practice Exercises
Exercise 1: Layering Dropdown Menus and Modals above Page Content
Scenario: An author uses structured z-index token values to manage stacking order between dropdowns, sticky headers, and modals.
Requirements:
- Define CSS custom properties for z-index tokens (
--z-sticky: 100,--z-modal: 1000). - Apply tokens to header and modal.
- Verify proper Z-axis layering.
Answer
Implementation
:root {
/* System Z-Index Token Architecture */
--z-dropdown: 10;
--z-sticky: 100;
--z-modal-backdrop: 900;
--z-modal: 1000;
--z-tooltip: 2000;
}
.sticky-header {
position: sticky;
top: 0;
z-index: var(--z-sticky);
}
.modal-dialog {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: var(--z-modal);
}
Technical Explanation
- The
z-indexProperty: Specifies the Z-axis stacking order of an element along the screen depth vector. - Positioning Prerequisite:
z-indexworks ONLY on elements with apositionvalue other thanstatic(relative,absolute,fixed,sticky), or flex/grid items! - Token-Based Architecture: Using CSS custom properties (
--z-modal: 1000) prevents arbitrary 'z-index wars' (z-index: 999999) across teams.
Exercise 2: Resolving Stacking Wars using Scaled Z-Index Tokens
Scenario: Refactors random z-index: 99999 values to structured design token scales.
Requirements:
- Replace arbitrary
z-index: 9999with semantic tokenvar(--z-tooltip).
Answer
Implementation
/* ❌ Arbitrary Z-Index War:
.tooltip { z-index: 9999999 !important; }
*/
/* ✅ Structured Token Scale: */
.tooltip {
position: absolute;
z-index: var(--z-tooltip); /* Controlled 2000 token layer */
}
Technical Explanation
- Z-Index War Pitfalls: Randomly guessing large
z-indexnumbers leads to unmaintainable stylesheets where components fight for dominance. - Scale Design: Use a 10/100/1000 step scale to leave space for future intermediate layers.
- Component Maintenance: Keeps component layering predictable across large development teams.
Exercise 3: Understanding Why z-index Fails on position static Elements
Scenario: Fixes a bug where z-index: 10 failed to apply on an element because position: static was active.
Requirements:
- Add
position: relativeto activatez-indexon static element.
Answer
Implementation
.card-overlay {
/* Fix: Add position: relative to activate z-index! */
position: relative;
z-index: 5;
margin-top: -2rem; /* Pulls card up over hero image */
}
Technical Explanation
- Static Z-Index Failure:
z-indexis completely IGNORED by browser layout engines onposition: staticelements. position: relativeActivation: Addingposition: relativeactivatesz-indexstacking capability without removing the element from normal flow.- Flex and Grid Exceptions: Immediate children of
display: flexordisplay: gridcontainers can usez-indexeven without explicitpositiondeclarations.
6. Related Terms
position: staticvsrelative— Required positioning properties.- Stacking Context — The parent layer grouping logic that shapes z-index behaviors.
overflow(hidden, scroll, auto, visible) — Related concept:overflow(hidden, scroll, auto, visible).position: absolutevsfixed— Related concept:position: absolutevsfixed.
7. Key Takeaways
z-indexcontrols which overlapping element is on top.- Higher numbers sit on top of lower numbers.
- You MUST apply
position: relative(or absolute/fixed) forz-indexto work! - Negative numbers (
z-index: -1) can be used to send elements behind their parent containers.