CSS z-index

Learn how to control element stacking order using CSS z-index property

What is CSS z-index?

The z-index CSS property controls the vertical stacking order of elements that overlap. It specifies the z-order of positioned elements and their descendants or flex items.

Key Properties:

  • z-index - Controls stacking order of positioned elements
  • position - Must be set to relative, absolute, fixed, or sticky for z-index to work
  • stacking context - Created by certain properties, isolates z-index of children
z-index: 10
z-index: 20
z-index: 30

z-index in Action

Example Code

/* z-index property controls stacking context */
.element {
  z-index: 10; /* Can be positive, negative, or auto */
}

/* Basic z-index usage */
.header {
  position: fixed;
  z-index: 1000; /* High value to stay on top */
}

.modal {
  position: absolute;
  z-index: 2000; /* Even higher for modals */
}

.background-element {
  position: relative;
  z-index: -1; /* Negative to go behind content */
}

/* Understanding stacking context */
.parent {
  position: relative;
  z-index: 0; /* Creates new stacking context */
}

.child {
  position: absolute;
  z-index: 10; /* Only competes within parent context */
}

/* Common patterns */
.dropdown {
  position: absolute;
  z-index: 100; /* Above normal content */
}

.tooltip {
  position: absolute;
  z-index: 200; /* Above dropdowns */
}

.overlay {
  position: fixed;
  z-index: 1000; /* High but below modals */
}

.modal-content {
  position: relative;
  z-index: 2000; /* Above overlays */
}

z-index Properties in Detail

z-index Values

The z-index property accepts integer values (positive or negative) or the keyword auto.

z-index: auto (default)
z-index: -1 (behind content)
z-index: 0
z-index: 1
z-index: 9999 (very high)

Positioning Requirements

z-index only works on positioned elements. The position property must be set to something other than static.

position: relative; z-index: 1
position: absolute; z-index: 2
position: fixed (simulated inside); z-index: 3
position: sticky; z-index: 4

Default Stacking Order

When no z-index is specified, elements stack in this order (from bottom to top):

1. Background and borders of the root element
2. Descendant blocks in normal flow, in order of appearance
3. Descendant positioned elements, in order of appearance

Stacking Context

A stacking context is a three-dimensional conceptualization of HTML elements along an imaginary z-axis relative to the user. Each stacking context is completely independent from other stacking contexts.

What Creates a Stacking Context?

  • The root element (HTML)
  • Positioned elements with z-index value other than "auto"
  • Elements with opacity less than 1
  • Elements with transform, filter, perspective, or clip-path properties
  • Elements with isolation: isolate
  • Flex items with z-index value other than "auto"
  • Grid items with z-index value other than "auto"

Stacking Context Behavior

Within a stacking context, child elements are stacked according to the same rules, but their z-index values only have meaning within their parent context.

.parent {
position: relative;
z-index: 1; /* Creates stacking context */
}

.child {
position: absolute;
z-index: 1000; /* Only matters within parent */
}

Stacking Order Within a Context

Inside a stacking context, elements are stacked in this order (from bottom to top):

1. Background and borders of the element forming the context
2. Elements with negative z-index (and their children)
3. Non-positioned elements in normal flow
4. Positioned elements with z-index: auto (or 0)
5. Elements with positive z-index (higher values in front)

Common z-index Patterns

Layering System

Many frameworks use a consistent layering system with predefined z-index values:

Dropdownsz-index: 1000
Sticky elementsz-index: 1020
Fixed headersz-index: 1030
Overlaysz-index: 1040
Modalsz-index: 1050
Tooltipsz-index: 1060
Notificationsz-index: 1070

Managing z-index

For large projects, it's helpful to manage z-index values systematically:

// z-index scale (as CSS variables)
:root {
--z-index-dropdown: 1000;
--z-index-sticky: 1020;
--z-index-fixed: 1030;
--z-index-overlay: 1040;
--z-index-modal: 1050;
--z-index-popover: 1060;
--z-index-tooltip: 1070;
}

.modal {
z-index: var(--z-index-modal);
}

z-index Troubleshooting

Common Issues

  • z-index not working (check if element is positioned)
  • Unexpected stacking due to nesting in different stacking contexts
  • Browser compatibility issues with certain properties that create stacking contexts
  • Overuse of high z-index values leading to "z-index wars"

Debugging Techniques

  • Use browser DevTools to inspect stacking contexts
  • Temporarily add borders or backgrounds to visualize stacking
  • Check if parent elements create stacking contexts
  • Use the Layers panel in browser DevTools to visualize stacking

Best Practices

  • Use the lowest possible z-index values that work for your needs
  • Create a z-index scale for your project and stick to it
  • Avoid creating unnecessary stacking contexts
  • Use CSS variables or preprocessor variables for z-index values
  • Document your z-index usage for maintainability

Practical z-index Examples

Modal Overlay

.overlay {
position: fixed;
top: 0; right: 0; bottom: 0; left: 0;
background: rgba(0,0,0,0.5);
z-index: 1040;
}

.modal {
position: fixed;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
z-index: 1050;
}
Modal Content

Dropdown Menu

.nav {
position: relative;
z-index: 100;
}

.dropdown {
position: absolute;
top: 100%;
z-index: 101;
}
Navigation
Dropdown Item 1
Dropdown Item 2
Dropdown Item 3

Card with Badge

.card {
position: relative;
}

.badge {
position: absolute;
top: -10px;
right: -10px;
z-index: 1;
}
3

Product Card

This card has a badge that overlaps the border

< Previous (Position)Next (Overflow) >