I am trying to understand why applying an opacity other than 1 to an element's child makes it always stack on top of the element's siblings.
.element {
width: 500px;
height: 100px;
background: orangered;
}
.child {
height: 150px;
width: 100px;
background: grey;
opacity: 0.5;
z-index: 1;
}
.sibling {
width: 400px;
height: 100px;
background: skyblue;
z-index: 2;
}
<div class="element">
<div class="child"></div>
</div>
<div class="sibling"></div>
Removing the opacity property (or setting it to 1) on the .child
makes it stack behind the .sibling
as expected, but for some reason an opacity value other than that changes its stacking order. It makes me think that .element
is somehow forming a stacking context, but as far as I can tell it doesn't meet any of the criteria on MDN's website.
The CSS standard doesn't have anything to say about this from what I understand:
Since an element with opacity less than 1 is composited from a single offscreen image, content outside of it cannot be layered in z-order between pieces of content inside of it. For the same reason, implementations must create a new stacking context for any element with opacity less than 1. If an element with opacity less than 1 is not positioned, then it is painted on the same layer, within its parent stacking context, as positioned elements with stack level 0. If an element with opacity less than 1 is positioned, the ‘z-index’ property applies as described in [CSS21], except that if the used value is ‘auto’ then the element behaves exactly as if it were ‘0’. See section 9.9 and Appendix E of [CSS21] for more information on stacking contexts. The rules in this paragraph do not apply to SVG elements, since SVG has its own rendering model ([SVG11], Chapter 3).
I think all its saying is that if you set opacity to something other than 1, then the element will form its own stacking context and everything inside the transparent element will be transparent together. But in my example, .child
may create its own stacking context for elements laid out inside of it, but the element itself would still be in whatever the surrounding stacking context is. This can be tested by setting display: flow-root
on .child
and removing opacity: 0.5
to force it to create a stacking context, but it will stack behind .sibling
as I would normally expect.
So what's going on here?