Isolate, don't raise z-index

isolation: isolate keeps a card's z-index from fighting the page.

Josh W. Comeaujoshwcomeau.com
When we apply this declaration to an element, it does precisely 1 thing: it creates a new stacking context.
What The Heck, z-index??Read article ↗
Josh W. Comeaujoshwcomeau.com
More and more, I'm starting to believe that z-index is an escape hatch , similar to !important .
What The Heck, z-index??Read article ↗

1 · A badge over the menu

Open the menu, then raise z-index values and watch who wins.

Badge leaks outBad
.card { position: relative }
Card isolatesGood
.card { isolation: isolate }
.card  { isolation: isolate; }   /* badge's z-index: 2 stays inside the card */
.badge { position: absolute; z-index: 2; }
.header { position: relative; z-index: 1; }   /* no 999 needed */

Why it matters, pros and cons

Why it matters

z-index only ranks siblings in one stacking context. A new context stops a badge's 2 from beating the header's 1.

Pros

  • One declaration on the component replaces every z-index: 999 on the page.
  • Inner layers keep their own small numbers and stay in order inside the card.
  • Nothing leaks, so a new teammate's z-index: 9999 can't break your component.

Cons

  • Anything that must escape the card, like a tooltip, gets clipped to its layer.
  • Other properties, like transform and opacity, also create contexts by accident.
  • You have to know which ancestor to isolate, and that takes a bit of DevTools.