On this page
Z-index & Stacking Contexts
CSS Z-index and Stacking Contexts: Complete Guide
Focus keyword: CSS z-index. Z-index controls which element appears in front when elements overlap. Many developers set z-index: 9999 and still see bugs, because z-index only works inside a stacking context. In this lesson you will learn how layering really works, what creates a stacking context, how to organise z-index values and how to debug overlapping problems.
Trending keywords covered in this lesson
z-index not working, stacking context, isolation isolate, z-index scale with CSS variables, painting order, dropdown behind element, modal overlay, transform creates stacking context, opacity stacking context, will-change, top layer, dialog element, popover attribute, negative z-index, layered design, CSS debugging.
1. What z-index Does
The z axis points from the screen towards the user. A higher z-index value is painted closer to the user. Z-index accepts integers (positive, zero or negative) or auto. It works on:
- Positioned elements (relative, absolute, fixed, sticky).
- Flex items and grid items, even when position is static.
On a normal static block element z-index is ignored. This is the number one reason for z-index not working.
2. Default Painting Order
Without z-index, elements are painted in this order inside one stacking context, from back to front:
- Background and borders of the context root.
- Negative z-index children.
- Normal flow block elements.
- Floated elements.
- Inline content (text).
- Positioned elements with z-index auto or 0, in HTML order.
- Positive z-index children, from low to high.
When two elements have the same level, the one later in the HTML is on top.
3. What Is a Stacking Context?
A stacking context is an isolated layer group. Children are sorted only among themselves, and the whole group is then placed as a single unit in its parent context. A child with z-index 9999 inside a context with z-index 1 can never rise above a sibling context with z-index 2.
Common ways to create a stacking context
- The root element (html).
- Positioned element (relative, absolute, fixed, sticky) with a z-index other than auto.
- Fixed or sticky elements (always, in modern browsers).
- Flex or grid item with a z-index other than auto.
opacityless than 1.transform,filter,perspective,clip-path,mask.isolation: isolate.mix-blend-modeother than normal.will-changefor a property that would create a context.contain: layout,paintorstrict.
4. isolation: isolate
isolation: isolate creates a stacking context on purpose without any side effects. Put it on a component root so its inner z-index values stay inside the component and never fight with the rest of the page. This is the cleanest fix for layering bugs and a modern best practice for design systems.
5. Organising z-index with a Scale
Avoid random numbers like 999999. Define a small scale with custom properties and use it everywhere:
--z-base: 0--z-dropdown: 100--z-sticky: 200--z-overlay: 300--z-modal: 400--z-toast: 500
Leave gaps so you can insert new layers later.
6. Negative z-index
A negative z-index sends an element behind its stacking context's in-flow content, useful for decorative backgrounds. If the parent does not create its own context, the element may go behind the parent's background and disappear. Add isolation: isolate to the parent to keep it visible.
7. The Top Layer: dialog and popover
Modern HTML offers the dialog element (with showModal()) and the popover attribute. They render in the browser's top layer, above all other content, regardless of z-index or ancestor stacking contexts. For modals, menus and tooltips, prefer them over manual z-index values.
8. How to Debug a Layering Bug
- Check that the element is positioned or is a flex or grid item.
- Walk up the ancestors and look for opacity, transform, filter, isolation or a positioned parent with z-index.
- Compare the z-index of the nearest shared stacking context, not of the two elements.
- Use browser DevTools: the Layers panel or the 3D view, and inspect computed styles.
- Fix by moving the element in the DOM, removing the accidental context, or adding isolation on the correct parent.
9. Common Mistakes
- Adding z-index to a static element.
- Increasing the number endlessly instead of finding the stacking context.
- Using transform on a parent and breaking a fixed or absolute dropdown inside it.
- Setting opacity on a wrapper and accidentally creating a context.
- Not keeping a shared z-index scale in the project.
Key Takeaways
Z-index is only compared within the same stacking context. Know what creates a context, use isolation: isolate on components, keep a z-index scale, and use dialog and popover for top-layer UI.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
Press Run to execute.
The dropdown appears behind the next card even though it has z-index 50. Find the stacking context problem and fix it so the dropdown shows above the second card.
Press Run to execute.
Show expected output
Dropdown is visible above Card 2 after giving Card 1 a higher z-index or removing the accidental stacking contextThis is a self-check — compare your result with the expected output above.
Create custom properties for dropdown, sticky, overlay and modal layers and use them on four elements so that modal is above overlay, overlay is above sticky and sticky is above dropdown.
Press Run to execute.
Show expected output
Variables like --z-dropdown, --z-sticky, --z-overlay, --z-modal with increasing values and used through var()This is a self-check — compare your result with the expected output above.
Was this page helpful?