Z-Index
When elements overlap — a dropdown over content, a modal over everything — z-index decides which one is on top. It is simple once you understand stacking contexts.
On this page · 6 min · Advanced
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 6 min
- Difficulty
- Advanced
- Updated
- Oct 28, 2026
Learning objectives#
- Use z-index to layer overlapping elements
- Know that z-index needs a positioned element (or flex/grid item)
- Understand stacking contexts
- Organise layers with a scale
Explanation#
By default, elements later in the HTML paint on top of earlier ones. z-index changes that: higher numbers come forward.
z-index only works on positioned elements (relative, absolute, fixed, sticky) and on flex or grid children.
A stacking context is a group whose children are layered only among themselves. Properties like opacity < 1, transform, filter, or position + z-index create one.
This is why z-index: 9999 sometimes “does not work”: if its parent is in a lower stacking context, the child can never rise above elements outside that parent.
Keep a small scale of named layers, e.g. dropdown 10, sticky header 20, overlay 30, modal 40, toast 50.
Code example: Layers and the stacking-context trap#
<style>
:root { --z-header: 20; --z-modal: 40; }
body { font-family: sans-serif; }
.box { position: absolute; width: 120px; height: 80px; padding: 6px; color: white; border-radius: 6px; }
.red { background: #dc2626; top: 10px; left: 10px; z-index: 3; }
.green { background: #16a34a; top: 40px; left: 60px; z-index: 2; }
.blue { background: #2965f1; top: 70px; left: 110px; z-index: 1; }
.stage { position: relative; height: 170px; }
.parent { position: relative; z-index: 1; background: #fef3c7; padding: 10px; height: 60px; }
.child { position: absolute; z-index: 9999; top: 30px; left: 20px; background: #7c3aed; color: white; padding: 6px; }
.sibling { position: relative; z-index: 2; background: #fde68a; padding: 10px; height: 60px; }
</style>
<div class="stage">
<div class="box red">z 3 — on top</div>
<div class="box green">z 2</div>
<div class="box blue">z 1 — bottom</div>
</div>
<div class="parent">Parent z-index 1
<div class="child">Child z-index 9999 — still underneath!</div>
</div>
<div class="sibling">Sibling z-index 2 covers the child</div>
Red sits on top of green, which sits on top of blue. Below, the purple child with z-index 9999 is still hidden by the sibling because its parent only has z-index 1.
Step-by-step explanation#
- Without z-index, blue (last in the HTML) would be on top.
- z-index 3, 2, 1 reverses the order.
- .parent with position and z-index 1 creates a stacking context.
- The child’s 9999 only competes with other children of .parent.
- .sibling at z-index 2 beats the whole .parent group, child included.
Real-world use case#
Dropdown menus hidden behind a sticky header, or a modal that appears under a carousel, are classic z-index bugs fixed by understanding stacking contexts.
Common mistakes#
A plain block with z-index and no position does nothing. Add position: relative.
Ever-higher numbers hide the real problem: a stacking context. Find the ancestor that creates it.
Adding transform (even for an animation) to a parent creates a stacking context and can trap a dropdown inside it.
Best practices#
- Use a small, documented z-index scale (CSS variables help)
- Render modals and toasts near the end of <body>
- Use DevTools 3D view / Layers panel to inspect stacking
- Use isolation: isolate to create a stacking context on purpose
Remember this#
Higher z-index = closer to you — but only among siblings in the same stacking context.
No position (or flex/grid parent)? No z-index effect.
A child can never climb higher than its parent’s layer.
Practice exercise#
Your task: A dropdown with z-index: 100 appears behind a sticky header with z-index: 10. The dropdown’s parent .toolbar has position: relative; z-index: 1. Fix it.
Need a hint?
Show solution
/* Raise the parent context above the header (or remove its z-index). */
.toolbar { position: relative; z-index: 11; }
Mini quiz#
Which element can use z-index?
Want more? Practise all CSS MCQs · CSS interview questions
My notes#
Saved in this browser.