← Back to all tutorials

Z-Index & Stacking Order

Understand how z-index controls which elements appear in front of or behind others, and how stacking contexts work.

Z-Index & Stacking Order

When elements overlap (due to positioning, transforms, or negative margins), the browser needs to decide which one appears on top. This is controlled by z-index and the stacking order.

What Is z-index?

z-index controls the stacking order of positioned elements along the z-axis (depth). Higher values appear in front of lower values.

.box-a {
    position: relative;
    z-index: 1;
}

.box-b {
    position: relative;
    z-index: 2;  /* Appears in front of box-a */
}

Important Rule: z-index Only Works on Positioned Elements

z-index only works on elements with a position value of:

  • relative
  • absolute
  • fixed
  • sticky

It does nothing on position: static (the default).

Default Stacking Order (No z-index)

Without z-index, elements stack in this order (back to front):

  1. Background and borders of the root element
  2. Non-positioned block elements (in DOM order)
  3. Non-positioned floating elements
  4. Non-positioned inline elements
  5. Positioned elements (in DOM order)

Later elements in the DOM appear in front of earlier ones.

z-index Values

ValueEffect
autoSame as parent's stacking context (default)
0Creates a new stacking context at base level
Positive (1, 10, 100)In front of lower values
Negative (-1)Behind elements with z-index: 0 or auto

Stacking Contexts

A stacking context is a group of elements that are stacked together as a unit. A z-index value only competes with siblings within the same stacking context.

A new stacking context is created when an element has:

  • position + z-index (not auto)
  • opacity less than 1
  • transform, filter, or perspective
  • isolation: isolate

Common z-index Scale

Use a consistent scale to keep z-index manageable:

/* z-index scale */
--z-dropdown:  100;
--z-sticky:    200;
--z-overlay:   300;
--z-modal:     400;
--z-popover:   500;
--z-tooltip:   600;

Common Mistakes

  • z-index on static elements — doesn't work; add position: relative
  • z-index wars — using z-index: 99999; instead, organize stacking contexts
  • Ignoring stacking contexts — a child with z-index: 9999 can't escape its parent's stacking context

Key Takeaways

  • z-index controls which positioned elements appear on top
  • Only works on positioned elements (not static)
  • Higher values appear in front of lower values
  • Stacking contexts isolate z-index comparisons
  • Use a consistent z-index scale instead of arbitrary large numbers