On 17 Jun 2009, Ben C <> wrote:
> On 2009-06-17, Neredbojias <> wrote:
>> On 16 Jun 2009, Ben C <> wrote:
>>
>>> On 2009-06-16, Neredbojias <> wrote:
>>>> On 16 Jun 2009, Ben C <> wrote:
>>> [...]
>>>>> opacity is only in CSS 3, but CSS 2.1 hints that setting opacity
>>>>> ought to start a stacking context (and it certainly should-- the
>>>>> alternative is insane).
>>>>
>>>> That sounds like it (er, the problem) but I'm not sure I follow
>>>> the reasoning. Why should opacity (or anything else) affect a
>>>> stacking order established by z-index?
>>>
>>> Because of the way opacity is defined.
>>>
>>> If you set opacity: 0.5 on an element, it's supposed to look as
>>> though that element _and all its descendents_ were rendered into a
>>> temporary buffer that was then blended on top of whatever the
>>> element is on top of with an opacity of 0.5.
>>>
>>> If the element didn't start a stacking context, then its
>>> descendents could be interleaved with other "foreign" elements from
>>> different stacking contexts that have full opacity.
>>>
>>> This creates a contradiction. If those foreign elements are
>>> rendered into the temporary buffer, then they will end up partially
>>> transparent, which they shouldn't be as they are not descendents of
>>> anything with opacity not equal to 1.0.
>>>
>>> But if they are not rendered into the temporary buffer, then they
>>> can't be interleaved with the descendents of the opacity: 0.5
>>> element and that would break the rules for stacking order.
>>>
>>> Here is an example:
>>>
>>> <div id="one" style="opacity: 0.5">
>>> <div id="two" style="z-index: 1"></div>
>>> <div id="three" style="z-index: 3"></div>
>>> </div>
>>> <div id="four" style="z-index: 2"></div>
>>>
>>> Suppose all divs are absolutely positioned, have widths, heights
>>> and solid background colours, and overlap each other.
>>>
>>> According to the rules as they stand, the browser does this (or
>>> equivalent):
>>>
>>> 1. Paint #one into a temporary buffer
>>> 2. Paint #two on top of #one in that temporary buffer
>>> 3. Paint #three on top of #two
>>> 4. Blend the temporary buffer onto the screen at opacity: 0.5
>>> 5. Paint #four onto the screen.
>>>
>>> The stacking order here is #one, #two, #three, #four (because #one
>>> starts a stacking context).
>>>
>>> But if opacity didn't start a stacking context, what would the
>>> browser be expected to do?
>>>
>>> 1. Paint #one into a temporary buffer.
>>> 2. Paint #two into the temporary buffer.
>>> 3. Paint #four on top of #two, but somehow not into the temporary
>>> buffer
>>> [impossible because #two _is_ in the temporary buffer]
>>> 4. Paint #three on top of #four, into the temporary buffer
>>> [impossible
>>> because #four _isn't_ in the temporary buffer].
>>> 5. Blend the temporary buffer onto the screen at opacity: 0.5
>>>
>>> The stacking order here would be #one, #two, #four, #three, on the
>>> assumption that opacity didn't start a stacking context.
>>
>> Criminey! Without perabusing the specs, I would've said the order
>> from top-to-bottom is four-three-two-one because two and three are
>> contained in/descendants of one (-even tho one has no positioning)
>
> It only works like that if #one starts a stacking context. If you
> don't set opacity on #one, the order should be 1, 2, 4, 3. Try it.
Indeed, I did, and indeed, that is how it is. So, apparently, the fact
that divs two and three are contained within div one (which is
positioned) does NOT subordinate the inner divs' stacking context in a
manner in keeping with other attributes assigned to elements "nested"
within a positioned container. At least the spec seems to indicate
thus. And, of course, I think they're dead wrong. What would be the
problem of doing so? It seems more logical, no?
>> and four has a bigger z-index than one whose children's z-indexes
>> are at a lower stacking level and irrelevant to that of four. Er,
>> is this what you said in reverse?
>
> That's what I said in reverse for the case where opacity _does_ start
> a stacking context.
>
>> Anyway, one and anything contained within it should
>> be opacity .5 and four should block out the whole "one thing"
>> solidly.
>>
>> Is this what the specs prescribe?
>
> Yes, assuming opacity does start a stacking context, as it should.
Well, not only opacity. I took your example -
<div id="one" style="opacity: 0.5">
<div id="two" style="z-index: 1"></div>
<div id="three" style="z-index: 3"></div>
</div>
<div id="four" style="z-index: 2"></div>
....removed the "opacity: 0.5" and replaced it with "z-index: 0". An
example page with and without this z-index on div one and the means of
applying opacity (via javascript) to both can be found at -
http://www.neredbojias.net/opa_z_tst.html
The set on the left has no div-one z-index thus allowing div four to
interleave stackwise between divs two and three which are contained in
div one, domed on the same "level" as div four. The set on the right
HAS a div-one z-index of "0" which I assume, like opacity, establishes
a "stacking context" under current specs and effects operation in a
manner I believe should be the norm. Mozilla and Safari seem to agree
to be, uh, "right" (-although doesn't Safari use the or similar to the
Gecko engine?) Opera, on the other hand, does something different.
(Explain that one to me... It seems to be worse.)
--
Neredbojias
http://www.neredbojias.org/
http://www.neredbojias.net/