DEV Community

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

Collapse
paceaux profile image
Paceaux • Edited on

The Stacking Context in CSS. More specifically, that there are a few CSS properties that can trigger a stacking context. And even more specific, that particular properties, in particular browsers, will give you very different results within that stacking context.

It'd started with a simple request to remove a double-scroll bar that was displaying in certain browsers. Over the course of a month I reviewed every CSS property on every element until I discovered that we'd unintentionally created a new stacking context, and that CSS we'd written accidentally handled that very well... until it didn't.

I ended up editing the mozilla developer network page on stacking contexts, and producing the most boring codepen ever that illustrates exactly how certain CSS properties totally bork stacking contexts.

took a month to discover that no one on the internet had, until then, documented that perspective would change the behavior of position:absolute. That double scroll bar was the hardest bug I ever tackled, but is also one of my proudest moments.

Collapse
gjeloshajantoine profile image
GjeloshajAntoine

I've never heard of stacking context in css!
What is it?

Collapse
devmount profile image
Andreas Author

In short: positioning and z-index. Paceaux provided a link with a detailed explanation. Here is an example:

stacking context example

Collapse
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.