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
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
z-index values of
#a p is positioned and has a positive stack level, it sits on top of both
#b within the root stacking context.
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.
- Elements with a negative stack level, typically elements with
- Elements with a
- Elements with a stack level of 0, typically positioned elements with a
- Elements with positive stack levels, e.g. a positioned element with a
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.:
filter when its value is something other than
mix-blend-mode when its value is something other than
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
In the example above,
#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.
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