CSS Tutorial
CSS Z-index
When elements overlap, z-index decides which one sits in front. Higher values come forward and lower values fall behind, giving you control over layers like dropdowns, modals, and tooltips.
The z-index property
By default, overlapping elements stack in the order they appear in the HTML — later elements paint on top of earlier ones. The z-index property overrides this by giving each positioned element a stacking number. An element with a larger z-index appears in front of one with a smaller z-index.
z-index only works on elements with a position value of relative, absolute, fixed, or sticky. On a static element it does nothing.
Layering overlapping boxes
The demo stacks three coloured boxes on top of each other. Their z-index values, not their HTML order, decide who wins the top layer.
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; }
.stack { position: relative; height: 160px; }
.box {
position: absolute;
width: 100px;
height: 100px;
color: white;
padding: 8px;
}
.red { background: #dc2626; left: 20px; top: 20px; z-index: 1; }
.green { background: #16a34a; left: 60px; top: 40px; z-index: 3; }
.blue { background: #2563eb; left: 100px; top: 60px; z-index: 2; }
</style>
</head>
<body>
<div class="stack">
<div class="box red">z-index 1</div>
<div class="box green">z-index 3 (front)</div>
<div class="box blue">z-index 2</div>
</div>
</body>
</html>| z-index value | Result |
|---|---|
| auto (default) | Uses natural HTML source order |
| Positive (e.g. 10) | Sits above lower-numbered siblings |
| 0 | Baseline layer within its context |
| Negative (e.g. -1) | Sits behind auto and 0 elements |
Sending an element behind with a negative value
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: system-ui, sans-serif; padding: 20px; }
.wrap { position: relative; }
.label {
position: relative;
z-index: 1;
font-size: 28px;
font-weight: bold;
color: #1e293b;
}
.behind {
position: absolute;
top: -6px;
left: -6px;
width: 220px;
height: 50px;
background: #fde68a;
z-index: -1; /* sits behind the text */
}
</style>
</head>
<body>
<div class="wrap">
<span class="label">Highlighted text</span>
<div class="behind"></div>
</div>
</body>
</html>Stacking context: why z-index sometimes fails
A stacking context is a self-contained layer group. When a parent creates one (for example by having its own z-index, or an opacity below 1), its children can never escape above the parent's level, no matter how huge their z-index is. If a big z-index seems ignored, an ancestor's stacking context is usually the cause.
Key points
- z-index needs a non-static position to take effect.
- Higher z-index values paint in front of lower ones.
- Negative z-index sends an element behind the default layer.
- Children are trapped inside their parent's stacking context — a huge z-index cannot break out.
