iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

z-index

Tailwind z-index scale: stacking order made predictable. The named layers, custom values, and the patterns that prevent z-index wars.

Tailwind — z-index

EXAMPLE
<!-- ===== Default scale ===== -->
<!-- z-0 z-10 z-20 z-30 z-40 z-50 -->
<!-- z-auto -->
<div class="z-0">base</div>
<div class="z-10">above</div>

<!-- Negative: -z-10 -z-20 ... -->
<div class="-z-10">behind</div>

<!-- ===== Arbitrary values ===== -->
<div class="z-[100]">specific</div>
<div class="z-[999]">very specific</div>

<!-- ===== Common UI layer plan ===== -->
<!--
  z-0    base content
  z-10   sticky elements (sidebar, header in flow)
  z-20   dropdowns
  z-30   sticky overlays (banner)
  z-40   modal backdrops + dialogs
  z-50   toasts + notifications

  Above 50: reserve for absolute top-of-stack (auth wall, debug overlay).
-->

<!-- ===== Custom scale in tailwind.config.js ===== -->
<!--
extend: {
  zIndex: {
    base: '0',
    dropdown: '20',
    sticky: '30',
    modal: '40',
    toast: '50',
    overlay: '999',
  },
},
-->

<!-- Then use: -->
<div class="z-modal">...</div>

<!-- ===== Stacking contexts ===== -->
<!--
A z-index only matters inside its STACKING CONTEXT.
A new context is created by:
  - position: relative/absolute/fixed/sticky + z-index != auto
  - opacity < 1
  - transform != none
  - filter, perspective, etc.

If your modal is inside a parent with opacity < 1, it WILL NOT escape that context.
Move overlays to a top-level portal to avoid this.
-->

<!-- ===== Common bug + fix ===== -->
<!-- The bug: nested z-index wars -->
<div class="opacity-90">              <!-- creates a stacking context -->
  <div class="fixed inset-0 z-50 bg-black/50">     <!-- still bounded by parent -->
    <div class="bg-white">Modal</div>
  </div>
</div>

<!-- The fix: render the modal in a portal at <body> root -->
<!-- React: ReactDOM.createPortal(<Modal/>, document.body) -->
<!-- Vue:   <Teleport to="body"><Modal/></Teleport> -->
<!-- Svelte: use:portal or a wrapper component -->

<!-- ===== Sticky + z ===== -->
<div class="sticky top-0 z-30 bg-white border-b">Header</div>
<!-- Sticky elements need a non-auto z-index to lay above content beneath. -->

<!-- ===== Pitfalls ===== -->
<!-- - Inflating z values to win wars (z-9999) hides root cause (stacking context) -->
<!-- - Forgetting that opacity / transform creates a new stacking context -->
<!-- - Mixing static + arbitrary values without a scale -->
<!-- - Tooltips inside a transformed parent -> appear behind unrelated elements -->

<!-- ===== Patterns to internalise =====
- Use 0/10/20/30/40/50 as named UI layers
- Portal modals + toasts to body root
- Avoid arbitrary z values; if you need 100+, you have a stacking context problem
- Document the layer plan once; teach the team
-->

Why it matters

Tailwind z-index works best when paired with a named layer plan (dropdown / modal / toast / overlay). The real bugs are stacking context — overlays inside opacity/transform parents do not escape. Portal them to body and the scale becomes predictable.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
<div class="relative z-10">Above</div>
Try it Yourself »

Discussion

Loading…