🌱BeginnerCSS Layout Basics
CSS Z-index and Stacking
Control which elements appear on top using z-index and understand how stacking contexts work.
Overview
When elements overlap on a page, CSS decides which one appears on top using a concept called stacking order. The `z-index` property lets you control this order explicitly.
By default, elements are painted in this order (back to front): block elements → floats → inline elements → positioned elements. Positioned elements (anything except static) already appear on top of non-positioned ones.
**z-index** only works on positioned elements (position: relative, absolute, fixed, or sticky). Higher z-index values appear on top of lower ones within the same stacking context.
A **stacking context** is an independent layer on the page. Creating one isolates z-index values a z-index: 9999 inside a stacking context cannot appear above elements outside that context. Stacking contexts are created by: position + z-index, opacity < 1, transform, filter, and others.
Key Points
- •z-index only works on positioned elements (not static)
- •Higher z-index = closer to viewer (on top)
- •z-index: auto element participates in parent stacking context without creating a new one
- •Stacking contexts isolate z-index: child z-index only competes within the parent context
- •Common triggers for new stacking context: position+z-index, opacity<1, transform, filter
- •Use small z-index values (1, 2, 10, 100) avoid huge arbitrary values like 99999
Examples
Basic z-index ordering
.card {
position: relative;
z-index: 1;
}
.modal {
position: fixed;
z-index: 100; /* always on top of cards */
}
.dropdown {
position: absolute;
z-index: 50; /* above cards, below modals */
}Establish a z-index scale: cards (1–9), dropdowns (10–49), modals (100–199), toasts (200+).
The stacking context trap
.parent {
position: relative;
opacity: 0.9; /* creates a stacking context! */
}
.child {
position: absolute;
z-index: 9999; /* high z-index, but only within .parent's context */
}
/* .child cannot appear above elements outside .parent,
no matter how high its z-index is */opacity < 1 creates a new stacking context. This is the most common source of z-index confusion.
Practical z-index scale
/* Define your z-index scale as custom properties */
:root {
--z-base: 1;
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 30;
--z-modal: 40;
--z-toast: 50;
}
.modal { z-index: var(--z-modal); }Common Mistakes
- Setting z-index on a static (position: static) element has no effect
- Using z-index: 9999 to "fix" layering usually means a stacking context is the real problem
- Not realizing opacity < 1, transform, and filter create new stacking contexts
Note
When z-index is not working, first check: (1) Is the element positioned (not static)? (2) Is there a stacking context ancestor (opacity, transform, filter) that is isolating it?
Exercises
Write CSS to style the HTML scaffold. The preview updates live — when it looks right, mark as done.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4