CSS Tutorial
CSS Z-index
z-index stacks positioned boxes. A new stacking context can trap a child behind a sibling.
Front to back
When two boxes overlap, the browser has to pick which one is painted on top. z-index is that order. Larger numbers sit closer to you. The property only applies to boxes that are positioned — notstatic — and to flex or grid items.
Without z-index, later HTML usually paints over earlier HTML. Harbor studio badges, menus, and overlays need an explicit stack so a teal chip does not vanish under a sky card.
Position first, then stack. A z-index on a static box is ignored. SeePosition if relative and absolute are still new.
Overlap on purpose
Both cards are position: relative so z-index can apply. The sky card is later in the HTML, but a lower z-index keeps it behind the teal slip.
Example
<style>
.dock {
position: relative;
height: 7rem;
}
.card {
position: relative;
width: 10rem;
padding: 0.75rem;
color: white;
}
.slip {
background: teal;
z-index: 2;
}
.sky {
background: #0284c7;
top: -2.5rem;
left: 4rem;
z-index: 1;
}
</style>
<div class="dock">
<div class="card slip">Slip 4 — Harbor studio</div>
<div class="card sky">Sky gallery waitlist</div>
</div>Stacking contexts trap children
A stacking context is a local stack. A child cannot jump out of it to sit above a sibling of its parent. Creating one is easy: position plus a z-index other than auto is enough. Opacity below 1, transform, and filter also create one.
If a badge on the lantern desk will not come forward, look at the parent. A parent withz-index: 1 can keep every child behind a neighbor with z-index: 2, no matter how large the child’s own number is.
Example
<style>
.row {
position: relative;
height: 6rem;
}
.desk, .quay {
position: relative;
width: 11rem;
padding: 0.75rem;
}
.desk {
background: #ccfbf1;
z-index: 1;
}
.ticket {
position: absolute;
top: 2.2rem;
left: 4rem;
z-index: 999;
background: teal;
color: white;
padding: 0.35rem 0.6rem;
}
.quay {
background: #0284c7;
color: white;
top: -1.5rem;
left: 5rem;
z-index: 2;
}
</style>
<div class="row">
<div class="desk">
Lantern desk
<span class="ticket">z-index 999</span>
</div>
<div class="quay">North quay sits above the ticket.</div>
</div>Raising a child’s z-index cannot beat a parent’s stacking context. Move the badge out, or raise the parent, or avoid giving the parent a z-index it does not need.
A simple scale
| Layer | Typical z-index | Harbor studio use |
|---|---|---|
| Page | auto or 0 | Cards, copy, berth map |
| Raised | 1–10 | Dropdown, sticky tide board |
| Overlay | 100–1000 | Modal, toast, skip link target |
You do not need 9999. A short scale is easier to debug. Negative values sit behind the parent’s background if the parent creates a stacking context.
In /css/try, lower the ticket to z-index: 0 and raise the quay. Then removez-index from .desk and watch the ticket escape the trap.
Worked examples
The short listings above show one property. These sheets paint documents you would actually ship: a lab dashboard, a clinic form, a marks table, a nav bar.
CSS does not invent meaning. HTML already said what the pieces are. Cascade, specificity, and the box model decide how they look. The numbers are classroom values — current, pH, pulse, 3-4-5 — so the style has something real to sit on.
Preview them in the CSS editor at /css/try. Change one property and watch the page paint. The tags stay the same.
Maths
Which tile is on top
z-index only applies to positioned boxes (relative, absolute, sticky, fixed). Higher number paints later, so it wins the overlap.
A new stacking context (opacity, transform, isolation) can trap a child. If a modal sits behind a header, look for a context, not only the number.
Example
<style>
.a, .b { position: relative; width: 90px; height: 50px; padding: 0.4rem; }
.a { background: #a5b4fc; z-index: 1; }
.b { background: #4338ca; color: #fff; margin-top: -20px; margin-left: 28px; z-index: 2; }
</style>
<div class="a">3</div>
<div class="b">5</div>Engineering
A toast over a dashboard
The teal tile is the later paint. In a real app the toast might be 1000 and the nav 100. Agree a scale so you are not in a z-index arms race.
Example
<style>
.dash { position: relative; background: #e0f2fe; height: 70px; }
.toast { position: absolute; right: 8px; top: 8px; background: #0f766e; color: #fff; padding: 0.3rem 0.5rem; z-index: 2; }
</style>
<div class="dash">Readings<div class="toast">saved</div></div>