If you've ever run into an issue with z-index
not working as you expect, there's a good chance it's because of stacking contexts.
The browser will stack elements based on their order in the DOM and their z-index
. But it also groups elements into stacking contexts. These are groups of elements that the browser treats as a single unit.
If two elements are in different stacking contexts, adjusting their z-index
will not change how they stack. You have to adjust how their stacking contexts are stacking:
<body><!-- First stacking context --><div class="stacking-context"><div id="a"></div><div id="b"></div></div><!-- Second stacking context --><div class="stacking-context"><div id="c"></div><div id="d"></div></div></body>
<style>/* These styles won't change anything */#a { z-index: 1; }#c { z-index: 2; }#b { z-index: 3; }#d { z-index: 4; }</style>
Because the second stacking context is above the first, we cannot get # a
to be above #c
. The stacking contexts overrule no matter how hard we try with z-index
or anything else.
However, if we change the z-index
of the stacking contexts, we can get # a' and
#bto appear above
#cand
# d`.
If we wanted to order them #a
, #c
, #b
, #d
, we'd have to change the HTML structure and move them all in to the same stacking context:
<body><!-- A regular div --><div><div id="a"></div><div id="b"></div></div><!-- Nothing special about this div --><div><div id="c"></div><div id="d"></div></div></body>
<style>/* These will change the visual hierarchy */#a { z-index: 1; }#c { z-index: 2; }#b { z-index: 3; }#d { z-index: 4; }</style>
You know a bit about stacking contexts, but what causes them, and how can you control them?
Unfortunately, the rules for creating them are not that straightforward, but well worth learning.