DEV Community

Discussion on: What was the weirdest bug you ever encountered?

paceaux profile image
Paceaux • Edited on

The stacking context is the ... well "context" in which the browser determines how to layer things. We hardly ever think about stacking context and it hardly ever matters.

But stacking context is about paint order ; when the browser has elements that overlap, the browser has to know which element to draw first, and which to draw next.

contrary to popular belief, z-index hasn't anything to do with positioning but with painting. When we have overlapping elements, and the browser is painting them in an order that we don't want, we use z-index to change the order in which the browser draws them.

So, that means that "the order in which the browser draws them" has to be determined some how. So what the browser does is find "root contexts" to determine which elements need to have their drawing order sorted out. Think of these "root contexts" as buckets with sheets of paper.

The bucket is any element with position:fixed, absolute, perspective, transform, etc. When the browser encounters those, it says, "aha! I need to make a bucket with this, and then figure out the order in which to paint things". That's your stacking context.

You can live a happy and fruitful career never having to think about this.

But occasionally you will discover that the browser sometimes has some strange rules about how it creates stacking contexts. Sometimes the browser has to change the rules of the bucket just to figure out how to paint those sheets of paper.

A great example of this might be an element that's position:fixed, with a parent container that has opacity: .2.

That position:fixed child element is _supposed to be` wherever you intend it to be, relative to the browser window.

But you see, it's inside of an opaque parent.

The browser is supposed to show just a little bit of the element underneath that parent, because the parent is opaque. That means the grandparent is supposed to influence the look of the grandchild.
But how can it do that if the grandchild is position:fixed and nowhere underneath this opaque parent? So the browser makes a decision:

I will create a "Positioning context" that matches the stacking context.

So what happens is position:fixed breaks . It's no longer relative to the window, it's relative to that parent that has opacity: .2.

Again, you can live a fruitful live never knowing about the Stacking Context because it mostly never matters. But there will be rare times where the browser can't reconcile these CSS properties where layering matters with other CSS properties where positioning matters, and it creates a new "positioning context" that matches the stacking context.