Search code examples
cssz-index

When/How does z-index break stacking context?


My understanding is that z-index elements are only stacked with their siblings. I've also read that z-index "doesn't work" with position: fixed. However, I'm using the two together and it happened to do exactly what I wanted it to; and I want to understand why.

I have a blocking div that needs to cover everything in the page except one element. The element is not a sibling of the blocker, which I thought would make it impossible, but it worked. What rule is being exploited here, and how can I predict if it will work in other browsers?

.top {
  background-color: yellow;
}

.yes {
  position: relative;
  z-index: 10;
  background-color: blue;
}

.no {
  position: relative;
  z-index: 1;
  background-color: red;
}

.blocker {
  position: fixed;
  z-index: 5;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, .7);
}
<div class="top">
  <button class="yes">
    Yes
  </button>
  <button class="no">
    No
  </button>
</div>
<div class="blocker">

</div>


Solution

  • Every non-positioned box belongs to the same stacking context that's established by the closest ancestor that meets any of the criteria listed here, or the root element if there is no such ancestor. This means that elements don't have to be siblings of one another in order to participate in the same stacking context. They may share a distant ancestor (in HTML, every element descends from the root element), but they don't have to share a parent.

    .top does not establish a new stacking context for its descendants .yes and .no as it is non-positioned and its z-index is auto. Therefore, .yes, .no and .blocker all participate in the same stacking context — the root stacking context. As a result the mere fact that .yes has a higher z-index than .blocker causes it to be painted in front.

    Note that while each of .yes, .no and .blocker does establish its own stacking context, the stacking contexts they establish are not pertinent here; it's the stacking context that they participate in, and they all participate in the same root stacking context.