Go back to home page of Unsolicited Advice from Tiffany B. Brown

CSS stacking contexts: What they are and how they work

Stacking contexts are an aspect of CSS that trips up most developers. I don't think I fully understood them until I wrote the layout chapter of CSS Master. Sure, I understood that z-index required position to be something besides static. But that's about as far as my comprehension went, even after reading Philip Walton's What No One Told You About Z-Index fiftyleven times.

That's no shade to Philip, by the way. Like I said: stacking contexts are tricky.

So what is a stacking context? A stacking context is an element that contains a set of layers. This can be a root stacking context, as created by the html element. Or it can be a local stacking context, as created by specific properties and values.

"Contains a stack of layers" is a weird phrase, but a simple concept. Within a local stacking context, the z-index values of its children are set relative to that element rather than to the document root. Layers outside of that context — i.e. sibling elements of a local stacking context — can't sit between layers within it.

Here's an example. Use the toggle to switch in and out of a local stacking context for A.

In this example, #a p (Child of A) has z-index: 1 applied, while #a and #b have z-index values of auto. Since #a p is positioned and has a positive stack level, it sits on top of both #a and #b within the root stacking context.

Changing transform: none to transform: scale(1) for #a, however, triggers a local stacking context. Now the z-index: 1 value for #a p is now calculated relative to #a instead of the document root.

Stacking contexts — whether local or root — follow a set of rules that determine the stacking and painting order of elements. Children of a stacking context are painted from bottom to top in the following order.

  1. Elements with a negative stack level, typically elements with z-index: -1
  2. Elements with a position value of static.
  3. Elements with a stack level of 0, typically positioned elements with a z-index value of auto.
  4. Elements with positive stack levels, e.g. a positioned element with a z-index value of 1 or higher.

Two elements with the same stack level are layered based on their source order. Successive elements stack on top of their predecessors.

A handful of CSS properties and values trigger a new stacking context. These include opacity when its value is less than 1 (e.g.: .99), filter when its value is something other than none, and mix-blend-mode when its value is something other than normal.

The transform property, as you may have guessed, is a property that can trigger a stacking context — but only when its value isn't none. This includes identity transforms1, such as scale(1) and translate3d(0,0,0).

In the example above, #a and #b have the same stack level, but #b is the second element in the source. When transform: scale(1) is applied, #a p becomes contained within the local stacking context of #a. As a result, #b rises to the top of the stack.

  1. Identity transforms have no visual effect on the element to which they're applied, but trigger a new stacking context. 

Get CSS Master

Did you learn something from this blog post? You might like the latest edition of CSS Master. It contains several nuggets of CSS joy like this one. Buy now from SitePoint