Chapter 5: Positioning, Z-Index & Stacking Contexts
The real reason your tooltip is behind the modal and how to debug layout layering
Every front-end developer has tried this at least once:
z-index: 99999;
…and then wondered why it still doesn’t work.
The truth is: z-index by itself is meaningless unless you understand what a stacking context is and how the browser builds visual layers.
This chapter will walk you through all of it.
Section 5.1: The 5 Position Values And What They Actually Do
static
(default)
- The default layout model.
- Element flows normally in the document.
top
,left
,right
,bottom
, andz-index
have no effect.
relative
- Keeps the element in normal flow.
- You can “nudge” it using
top
,left
, etc. - Important: It becomes a reference point for absolutely positioned descendants.
.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
left: 0;
}
Now .child
is anchored to .parent
, not the page.
absolute
- Element is removed from normal flow.
- Positioned relative to the nearest ancestor with
position: relative | absolute | fixed | sticky
.
If no such ancestor exists → the reference is the <html>
element.
fixed
- Removed from flow.
- Always positioned relative to the viewport.
- Doesn’t move when you scroll.
Used for:
- Modals
- Toasts
- Sticky navbars
sticky
- Hybrid: acts like
relative
until it reaches a threshold, then becomesfixed
. - Needs:
- Scrollable ancestor
top
orleft
defined
Section 5.2: What Is Z-Index?
z-index
controls which element sits on top when they overlap.
Higher z-index
= closer to the user
But: z-index
only applies if the element is positioned.
.modal {
position: fixed;
z-index: 10;
}
No position
, no z-index
.
Section 5.3: The Stacking Context, What Nobody Taught You
A stacking context is like an isolated z-index world.
Inside a stacking context:
- Elements stack based on
z-index
- But outside elements can’t penetrate it no matter how high their
z-index
New stacking context is created by:
position
+z-index
opacity
less than 1transform
,filter
,will-change
isolation: isolate
contain: layout | paint
mix-blend-mode
values
Example:
.parent {
position: relative;
z-index: 0;
}
.child {
position: absolute;
z-index: 9999;
}
If .parent
is in a lower stacking context, .child
cannot escape it.
Even if .child
has z-index: 999999999
, it will still render behind a sibling .modal
with its own stacking context and z-index: 10
.
Section 5.4: How the Browser Builds the Stack
- Start with the root stacking context (
<html>
) - Look for any element that creates a new stacking context
- Inside each context, z-index defines order
- Higher contexts render over lower ones regardless of child z-index
Section 5.5: Debugging Stacking Contexts in DevTools
Chrome DevTools can help:
- Inspect an element
- Go to Computed → z-index
- Look at Stacking Context
- Use the Layers panel to see visual layers
Tip: Enable “Show stacking contexts” in DevTools experiments
You’ll see purple outlines around elements creating new stacking contexts.
Section 5.6: Common Stacking Bugs (And Real Fixes)
Tooltip hidden under image
.tooltip {
position: absolute;
z-index: 1000;
}
But .container
has:
.container {
opacity: 0.99;
}
Boom new stacking context. Tooltip can’t escape.
Fix: remove opacity or raise parent context’s z-index
Modal behind backdrop
.backdrop { z-index: 999; }
.modal { z-index: 1000; }
But .modal
is inside a relative
parent with z-index: 1
.
Fix: raise parent’s z-index or move .modal
outside the constrained context.
Section 5.7: Practical Strategies for Layering
Group your layers:
Layer | z-index range |
---|---|
Base UI | 0–10 |
Dropdowns | 100–500 |
Modals | 1000–1500 |
Toasts | 2000+ |
Use utility variables or CSS layers:
:root {
--z-modal: 1000;
--z-dropdown: 500;
}
.modal {
z-index: var(--z-modal);
}
Section 5.8: Isolation and GPU Promotion
Sometimes you need to isolate an element fully:
.container {
isolation: isolate;
}
This cuts off the stacking flow and prevents accidental interference.
Also:
transform: translateZ(0);
creates a new compositing layer- Good for fixing stacking bugs but use sparingly (can impact performance)
Summary: Z-Index & Position
- Always pair
z-index
withposition
- Stacking contexts isolate z-index calculations
- Use consistent layer values (not
z-index: 999999
) - Debug visually in Chrome’s DevTools + Layers panel
- Prevent bugs with
isolation: isolate
, remove unintendedopacity
,transform
, orfilter
Learn More
Coming Up Next
In Chapter 6, we’ll compare Flexbox, Grid, and normal layout flow and give you a real strategy for choosing the right tool for the job.