Z-Index & Stacking

Layer Order Without Magic Numbers

Z-Index & Stacking

Manage stacking with z-index utilities and understand when a stacking context is created.

4 min read Level 1/5 #tailwind#layout#zindex
What you'll learn
  • Use the z-index scale and arbitrary values
  • Know what creates a stacking context
  • Use isolate to contain z-index

z-index decides what sits on top of what. Tailwind gives you a small scale so you stop inventing z-index: 9999 numbers that fight each other forever.

The z-index Scale

<header class="sticky top-0 z-10">nav</header>
<div class="z-50">modal layer</div>
<div class="z-[999]">rare escape hatch</div>

The scale goes z-0, z-10, z-20, z-30, z-40, z-50, plus z-auto. Standardizing on these prevents the arms race. Arbitrary values like z-[999] exist but should be a red flag prompting you to rethink the layering.

z-index Only Works on Participants

A crucial gotcha: z-index has no effect on a static-positioned element. It only applies to elements that are positioned (relative, absolute, fixed, sticky) or are flex/grid children. If your z-50 does nothing, the element is almost always still static:

<!-- z-10 is ignored: still static -->
<div class="z-10">no effect</div>

<!-- z-10 now works -->
<div class="relative z-10">on top</div>

Contain Layers with isolate

z-index values compete within the same stacking context. A common bug is a card’s decorative layer at z-10 accidentally rendering above an unrelated dropdown elsewhere on the page. isolate creates a fresh stacking context, sandboxing all child z-index values inside the component:

<div class="relative isolate">
  <div class="absolute inset-0 -z-10 bg-gradient-to-br from-blue-100"></div>
  <div class="relative z-10">content above the decorative gradient</div>
</div>

Because of isolate, the inner -z-10 and z-10 only matter relative to each other — they can never escape the card and clash with the rest of the page. Reaching for isolate is almost always better than escalating z-index numbers.

Aspect Ratio & Object Fit →