Skip to content

anything that creates a stacking context should sort in the positioned descendants z-ordering list #2717

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Tracked by #4965
dbaron opened this issue May 30, 2018 · 11 comments
Labels

Comments

@dbaron
Copy link
Member

dbaron commented May 30, 2018

CSS 2.1 Appendix E, about painting order has a basic separation between handling of descendants that are positioned (painted in steps 3, 8, and 9) and things that are not positioned (painted in steps 4, 5, 6, and 7). It defines that separation in terms of "positioned descendants". Note that in level 2 of CSS, positioning is the only thing that causes creation of a stacking context (via the interaction of position and z-index).

There are a substantial number of features introduced in CSS since level 2 that create stacking contexts. These include: opacity, transforms (via transform, perspective, transform-style, rotate, scale, or translate), isolation, filter, mix-blend-mode, clip-path, and mask/mask-image, will-change, and contain. (These are the ones implemented in Gecko.)

Some of the specifications of these properties define not only that a stacking context is created, but that elements with the property are painted as though they were a "positioned descendant". For example, the spec for opacity says:

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

Some of the other specs don't, however, explicitly require this.

I believe that, since the rules for painting descendants in steps 4-7 assume that floats are intended to interleave between the block-level and inline-level descendants of an element, those rules don't make sense for any of the features that create stacking contexts.

I think the current situation of vague specs has led to implementation bugs. In Gecko, for most of these features, we've assumed that they should be painted in the order used for positioned descendants, but we haven't done this for isolation or will-change. I suspect that may produce strange results (the code looks like we paint them at the order of inline content, which means they'll be storted incorrectly relative to later inline content or earlier positioned elements or stacking contexts). We'd like to fix this and might move ahead with doing the same for isolation and will-change in the absence of a clear direction here.

I think that:

  • all of the features that create stacking contexts should lead to an element being painted at the position reserved in CSS 2 for positioned descendants
    • I believe Gecko's Web compatibility shows this is safe for properties other than isolation, contain, and will-change, though it's still worth investigating what other engines do.
  • we should edit CSS 2 to reflect this change, i.e., that everything that creates a stacking context is painted in steps 3, 8 (not using the auto variant!), and 9. This will tie the behavior to the definition of stacking contexts and make it much harder for new specifications to get this wrong.
  • this edit needs to be done carefully since:
    • z-index only applies to elements that are actually positioned
    • when a stacking context is created, z-index: auto becomes z-index: 0 (even when it "doesn't apply")
  • we could consider applying z-index to elements other than positioned elements, although there may be compatibility risk (I haven't tested behavior across engines)
@dbaron
Copy link
Member Author

dbaron commented May 30, 2018

Also:

  • since this is a common pattern (the transform-related properties, contain, filter), the spec should probably introduce an additional, stronger, term, that means the combination of:
    • establishes a stacking context, and
    • establishes a containing block for absolute and fixed positioned descendants.

@dbaron
Copy link
Member Author

dbaron commented May 31, 2018

I've attempted to write a comprehensive test of the relevant cases.

@dbaron
Copy link
Member Author

dbaron commented Jun 1, 2018

To answer some of the questions I was trying to address with the testcase:

1. Is creating a stacking context equivalent to sorting in the positioned descendants list? (Basically, does the first test column agree with the following two?)

  • in Chrome and WebKit, these are equivalent
  • in Gecko, they're equivalent except that isolation and will-change don't trigger sorting in the positioned descendants list, but do create a stacking context
  • in Edge, the exception is mask-image (in the same way)

2. What implemented properties don't cause creation of a stacking context in implementations but are specified to do so?

  • In all 4 engines, transform-style: flat
  • in WebKit, also clip-path mask (though they actually do as values of will-change)
  • in Chromium, mask (and also broken as a value of will-change), and will-change: contain (but not contain itself)
  • in Edge, mask

3. What properties create a containing block for fixed-positioned elements?

  • in Gecko:
    • all the transform things (transform, perspective, transform-style: preserve-3d) that create stacking contexts (Gecko doesn't yet implement translate, rotate, and scale)
    • filter
    • (plus some other properties that are not actually enabled but their will-change support is inadvertently enabled)
  • in Chromium:
    • all the transform things (the Gecko list plus translate, rotate, and scale) that create stacking contexts
  • in WebKit:
    • only transform
  • in Edge:
    • all the transform things (same list as Chromium) that create stacking contexts

@birtles
Copy link
Contributor

birtles commented Jun 1, 2018

Gecko implements translate, rotate, scale but they're pref-ed by default (layout.css.individual-transform.enabled).

@dbaron
Copy link
Member Author

dbaron commented Jun 1, 2018

Gecko also implements parts of contain behind a flag.

Also, the WG resolved that filter should be a containing block for abs-pos and fixed-pos descendants.

@tabatkins
Copy link
Member

Yo, @chrishtr, can you review this? I'm pretty sure you'd be in favor.

@css-meeting-bot
Copy link
Member

The Working Group just discussed anything that creates a stacking context should sort in the positioned descendants z-ordering list.

The full IRC log of that discussion <dael> Topic: anything that creates a stacking context should sort in the positioned descendants z-ordering list
<dael> github: https://github.com//issues/2717
<dael> dbaron: I think at this point it's calling attention to it rather then resolve
<dael> dbaron: Underlying issue is due to how we structured our specs we changed things relating to paining order and stacking context without patching this cnetral stuff.
<dael> dbaron: I proposed that everything that creates a stacking context paints where css 2.1 paints
<fantasai> dbaron++++++++
<dael> dbaron: I tried to create test cases. Lots of non-interop. Underlying principle seems entirely followed by chrome and webkit. Mostly followed by gecko. Edge might be futher, but might be due to bug. Cases where gecko didn't follow is when an impl literally followed spec and did nothing else and got different.
<dael> dbaron: Other thing worth discussing is if people agree anythign creates a stacking context should cause something painted as a descendant.
<fantasai> dbaron, makes sense to me
<dael> TabAtkins: I think Chris H. would be in favor of it. I'll ping him into the thread.
<dael> dbaron: Chrome follows the principle exactly I think
<dael> dbaron: I wrote a comment in the issue with the exceptions. chrome and webkit are eq.
<dael> dbaron: When you start looking at which properties are supposed to create stacking context there's lack of interop
<astearns> it's @chrishtr
<dael> florian: Suggestion is patch css 2 for more generic worded statement?
<dael> dbaron: Part of it is css 2 needs to introduce terms other specs can add. It says positioned element. We need a term...I thought it's in the issue...I didn't propose a name. But we need a term.
<dael> florian: Other terms?
<dael> dbaron: We need a second that's for elements that create a stacking context and become a containing block. Since that doesn't exist in L2 it could be introduced in an L3 spec
<dael> Rossen: I looked briefly a couple weeks ago. Thought at the time is...we have opacity which is a stacking context but not containing block. display:fixed which is stacking not containing. We have transforms that are stacking and containing blocks including fixed.
<dael> Rossen: Is that what you're proposing to add...alll of this?
<dbaron> https://dbaron.org/css/test/2018/stacking-context-z-order
<dael> dbaron: There's other pieces
<dael> dbaron: In the big test case ^ there's a lot of details
<gsnedders> dbaron: or in 2.2, surely?
<dael> dbaron: Things I think are supposed to...everything on the left except red background should create stacking. Things with green box I think also create containing block for fixed pos.
<dael> dbaron: Based on current spec and current resolutions that aren't yet edited in
<dael> Rossen: This is a really good summary of all the different combinations which I had not seen. Sorry. I want to go over this and make sure we can cross our t and dot our i.
<dael> dbaron: I think if anything I might want resolution on general principle we'd like to make them eq if we can get away with it, stacking context and position descendants layer. fixed pos is only somethings definitely.
<dael> dbaron: But totally fine taking time
<dael> dbaron: I tried to make a list of bugs at the bottom
<dael> Rossen: Other thing that I don't see in write up or matrix is there are...also the discussion about body and html in the root and filter on html or body would behave
<dael> dbaron: I think we had sep. resolution on that
<dael> Rossen: filter should effect scrolling for viewport or not for example?
<dael> dbaron: I rememebr we discussed that for filter or mask. I'd like to keep root stuff sep.
<dael> Rossen: That's fine. When it comes to, especially the fixed containing box drama would be great. And that's where all the root and body and filter drama comes into play
<dael> Rossen: Without considering the reverse style propagation it's hard.
<dbaron> we had some discussion about filter and body/root in https://github.com/w3c/fxtf-drafts/issues/11
<dael> dbaron: I'll link to another issue where we discussed that, I think
<dael> astearns: Sounds like we all need to look more and come back to see if we can resolve. It'd like to in part to get these tests into wpt
<dael> Rossen: Want to make sure we'll cast a wide net and put this to rest.
<dael> astearns: Right
<dael> astearns: Anything more to discuss this week?
<dael> dbaron: I'm fine with later.
<dael> astearns: Maybe a F2F
<dael> Rossen: One more to add, filter opacity vs. opacity does the right thing per spec.
<dael> dbaron: Yeah. I just picked a random filter for my test, but yes.
<dael> Rossen: Reason why is this on we've had confusion where people expect opacity and filter opacity behave the same and it doesn't for fixed pos.

@astearns astearns removed the Agenda+ label Jun 7, 2018
@chrishtr
Copy link
Contributor

chrishtr commented Jun 8, 2018

I am in favor of making a stacking-context-inducing properties result in the element being painted at the same time as positioned elements, mainly for practical and interop reasons. (*)

(One point regarding mask: Chromium does in fact apply paint-as-if-positioned for masks, but mask is still a prefixed property in Chromium (-webkit-mask).)

However, we should also revisit the relation between various kinds of replaced or scrolling content, paint-as-if-positioned, and stacking contexts. Here is some research I have done:

  1. <foreignObject>: Edge, Safari, Gecko and Chromium (as of Chromium 67) treat "as a stacking context", but do not paint-as-if-positioned for this element. To support this combination, Chromium recently added code to support the concept of a "replaced normal flow stacking context", which previously was not supported.

  2. <video>: Chromium implements video overlay controls underneath user-agent shadow DOM that is a descendant of the

  3. <iframe>: iframe elements paint-as-if-positioned in Chromium, WebKit, Gecko and Edge. The iframe contents are painted atomically, but since they are from a different frame the question of stacking context doesn't apply.

  4. Scrolling. Chromium and WebKit both paint-as-if-positioned if overflow:scroll is present and there is actual overflow; otherwise they do not paint-as-if-positioned. Until recently, Chromium only applied this quirk for composited scrolling; WebKit may still have this restriction. Neither Gecko nor Edge do this.

A long-standing bug in Chromium and WebKit (crbug.com/370604) makes it hard to achieve interop with (4), but Chromium is working towards a fix.

This testpage demonstrates the above examples: http://output.jsbin.com/teyiwiz/15/quiet

(*) In fact, I think a thorough revision and update to this algorithm should be done to incorporate the latest state of actual browsers and spec currently-undefined behavior.

@frivoal
Copy link
Collaborator

frivoal commented Aug 29, 2018

Just re-ran into this while looking at tests for css-contain. This issue is defined broadly, and I am not sure we have agreement on all the subpoints (thought it'd be great if we did), but If I'm reading the minutes correctly, it looks like there is agreement that making a stacking-context-inducing properties should result in the element being painted at the same time as positioned elements.

Agenda+ to try and resolve that that sub-problem.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed anything that creates a stacking context should sort in the positioned descendants z-ordering list.

The full IRC log of that discussion <dael> Topic: anything that creates a stacking context should sort in the positioned descendants z-ordering list
<tantek> lol "perfectly fine HTML elements". ok agree to disagree
<dael> github: https://github.com//issues/2717#issuecomment-416803673
<dael> florian: I ran into this again while writing tests for Contain. Summary: place in the spec that defines how things stack is in css2.1 THat bit of prose assumes only things that can create stackign context are positioned elements so it's not careful in phrasing. We've introduced other things so we need to clarify if they stack same or not.
<dael> astearns: Stacking or painting?
<dael> florian: I'm not the expert on stacking and painting. I jsut want this closed.
<dael> dbaron: I think most of answer in the issue. Someone needs to propose edits to css2 with a new term, only onething in css2 uses the term, all other specs use that term.
<dael> chrisl: Not just css2. Also compositing defines more. I agree we need clarity and changes, but all in css2 is not optimum.
<dael> dbaron: Things that should be in compositing, I agree. Term in css2 is 'thing that creates stacking context'. When css 2 refers to that term it says 'positioned elements' and it needs a term so other specs can say this thing creates stacking context so all things css2 says about stacking context applies
<dael> chrisl: agree on that
<dael> florian: Given css2 has editors can we assign somebody?
<dael> tantek: File and issue and take it from there
<Rossen_> :)
<dael> fantasai: gsnedders is still looking for funding to work on css2 so if you want him to be an effective editor give him some money
<dael> astearns: I like idea of separate issue for css2 work o nthis
<dael> florian: Is it separate or just the same?
<dael> tantek: Yes
<dael> dbaron: Edit other specs. Separate issue makes sense
<dael> tantek: Fixing css2 is not signing up for all other specs
<dael> dbaron: And fixing css2 is complicated because you have to find all the places to change for the new term
<dael> astearns: tantek can you create issue?
<dael> tantek: Not failiar. I'd ask current issue creator
<dael> dbaron: I'll file and issue
<dael> astearns: Anything more?

@MatsPalmgren
Copy link

w3c/fxtf-drafts#282 might be relevant to this issue.

kalenikaliaksandr added a commit to kalenikaliaksandr/ladybird that referenced this issue Oct 9, 2024
...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).

See following spec issue for more details w3c/csswg-drafts#2717

Visual improvement on https://basecamp.com/
kalenikaliaksandr added a commit to kalenikaliaksandr/ladybird that referenced this issue Oct 9, 2024
...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).

See following spec issue for more details w3c/csswg-drafts#2717

Visual improvement on https://basecamp.com/
kalenikaliaksandr added a commit to kalenikaliaksandr/ladybird that referenced this issue Oct 9, 2024
...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).

See following spec issue for more details w3c/csswg-drafts#2717

Visual improvement on https://basecamp.com/
kalenikaliaksandr added a commit to LadybirdBrowser/ladybird that referenced this issue Oct 9, 2024
...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).

See following spec issue for more details w3c/csswg-drafts#2717

Visual improvement on https://basecamp.com/
ebanner pushed a commit to ebanner/ladybird that referenced this issue Oct 15, 2024
...traversal. We've already fixed step 3 and 9 to not filter out
non-positioned stacking contexts, because modern CSS has more ways to
create stacking context besides being positioned with z-index (like by
using "transform", "filter" or "clip-path" properties).

See following spec issue for more details w3c/csswg-drafts#2717

Visual improvement on https://basecamp.com/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants