Skip to content
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

can SVG container elements establish containing block for absolute/fixed positioned elements? #307

Open
dbaron opened this issue Aug 3, 2018 · 9 comments

Comments

@dbaron
Copy link
Member

dbaron commented Aug 3, 2018

Currently the spec for filter, if interpreted literally, says that when filter is applied to SVG container elements, then those elements establish a containing block for fixed positioned and absolutely positioned elements.

It's not clear to me what this means, since it's not clear to me where the edges of such a containing block are.

On the other hand, it also doesn't make sense for these elements to escape the filter. One way to avoid that would be to say that <foreignObject> establishes such a containing block, but I'm not sure if that would be web compatible.

I think this also applies to a number of other properties (will-change, contain, and a bunch of transform properties although those properties currently have an exception for elements not governed by the CSS rendering model... which in turn raises the question of how a transformed element that is position:fixed to an ancestor behaves.

@tabatkins
Copy link
Member

The proper resolution to this boils down to "actually define how SVG operates in the CSS box model finally", correct? (Aka the thing I've been saying I'd do for a few years now...)

@AmeliaBR
Copy link

AmeliaBR commented Aug 3, 2018

One way to avoid that would be to say that establishes such a containing block, but I'm not sure if that would be web compatible.

That is probably the most logical approach, and most useful.

The SVG 2 specs define <foreignObject> as creating a stacking context, so that already covers containing absolutely-positioned elements. I don't think there is any argument against that.

Fixed positioning is a little more complicated, since currently filters & transforms are the only things that contain fixed elements, and I don't think there's any spec that says SVG should have an effect. But nonetheless, browsers seem to agree that it does, although they don't agree in all the details.

I'm using this Codepen, which is a modified version of this WPT test. The WPT test is very problematic; the failures are about how offsetLeft is calculated, while the passes (Chrome vs WebKit) don't actually agree on layout!

Anyway, here are my results for latest stable Chrome, Edge, Safari & Firefox Dev edition:

  • Static (Spring green) and relative (Rebecca Purple) elements:

    • all browsers position as expected, except that Safari collapses the margins through the edge of the foreignObject container, while the others contain margins.
  • Absolute (Alice Blue) element:

    • Chrome, Firefox & Edge all position relative to the foreignObject parent.
    • Safari positions relative to the initial containing block, I think.
  • Fixed (Firebrick) element:

    • All 4 browsers position the element relative to the foreignObject bounds
    • However, Chrome then fixes its position relative to scroll on the body, although it disappears if you scroll enough so that is completely outside of the foreignObject bounds.
  • Sticky (Steel Blue) element:

    • MS Edge crashes the tab (the element is commented out in the pen to avoid this)
    • Firefox and Chrome position it as expected from static layout, then scrolls it stickily (relative to scroll on the body) while containing it within the foreignObject bounds.
    • Safari doesn't support sticky positioning (I didn't try with -webkit-).

So, in conclusion:

I'd say your proposal isn't a web compat problem, but we need some specs & tests to match, and then some bugs filed on browsers.

The proper resolution to this boils down to "actually define how SVG operates in the CSS box model finally", correct?

That would cover a lot of it, yes...

@atanassov
Copy link

Establishing stacking context doesn't mean establishing a containing block. Ideally we can define as establishing an initial containing block.

@chrishtr
Copy link
Contributor

chrishtr commented Aug 8, 2018

<foreignObject> is treated as a containing block for all descendants in Chromium. It's also a stacking
context, as of Chromium 67.

The SVG2 spec says, at least indirectly, that <foreignObject> is both a stacking context and containing block. This sentence in particular:

"Since the ‘foreignObject’ element creates a "fixed position containing block" in CSS terms..."

Therefore it's web compatible, as far as it concerns Chromium, to define SVG container elements
as establishing a containing block for all descendants.

@chrishtr
Copy link
Contributor

chrishtr commented Aug 8, 2018

Fixed (Firebrick) element:

All 4 browsers position the element relative to the foreignObject bounds
However, Chrome then fixes its position relative to scroll on the body, although it disappears if you scroll enough so that is completely outside of the foreignObject bounds.

I don't see this behavior. On what version of Chrome are you testing? Could you please file a bug
at crbug.com with exact repro steps?

@dbaron
Copy link
Member Author

dbaron commented Aug 8, 2018

Therefore it's web compatible, as far as it concerns Chromium, to define SVG container elements
as establishing a containing block for all descendants.

I'd much rather do this for <foreignObject> (as you say Chromium does) but not for SVG container elements in general (both since I think doing it for <foreignObject> makes it irrelevant, and because it would be hard to define reasonably).

@chrishtr
Copy link
Contributor

chrishtr commented Aug 8, 2018

since I think doing it for makes it irrelevant

I agree that this fact makes it irrelevant whether these elements are "containing blocks".

I meant to say earlier that, if it makes it easier to write the spec text not special-case such elements, then great. If not, then not.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed SVG container elements, and agreed to the following:

  • RESOLVED: svg spec says that <fO> creates a containing block for fixpos and abspos children
The full IRC log of that discussion <TabAtkins> Topic: SVG container elements
<astearns> github: https://github.com//issues/307
<TabAtkins> AmeliaBR: Filters create a containing block for abspos/fixpos
<TabAtkins> AmeliaBR: When specified nobody thought about SVG, because it doesn't ahve abspos.
<TabAtkins> AmeliaBR: But you can do a foreignContent with html that uses abpos. dbaron wondered what happens there.
<TabAtkins> AmeliaBR: Looking at browsers, they're non-interop.
<bkardell_> is this totally related? https://github.com/w3c/mathml/issues/48
<TabAtkins> AmeliaBR: In discussion, consensus seems to be that the foreignObject is a containing block for abspos/fixpos, so you dont' have to worry about whether an ancestor svg el has a filter or not.
<TabAtkins> AmeliaBR: That's what Chrome does
<TabAtkins> AmeliaBR: So we need to specify foreignObject better in general about hwo it provides a containing block for css content insie of it, and making this dfn makes things simpler, but it does add a new place where we're trapping fixpos elements.
<TabAtkins> astearns: chrishtr says that the SVG spec already defines that foreignObject defines a fixpos containing block
<TabAtkins> AmeliaBR: Maybe
<TabAtkins> mstange: I think all browsers already agreeo nthis
<TabAtkins> mstange: The difference amelia found might be an old versio nof chrome; i think browsers now agree
<TabAtkins> mstange: I think having fO be a containing block for everything makes a lot of sense
<TabAtkins> AmeliaBR: Weird ones that dont' match are Safari: <fO> contains fixpos but not abspos. stickypos is a big untested mess too
<TabAtkins> mstange: We may want to add something about stick to the spec, then?
<TabAtkins> iank_: Maybe better as a separate issue
<TabAtkins> dbaron: I don't think anything special needs to happen with sticky, because I don't think it escapes very far
<TabAtkins> AmeliaBR: I think the dfn of what happens with it will fall out of defining it as a containing block
<TabAtkins> emilio: sticks is about scroll containers, not containing block
<TabAtkins> astearns: so what needs to be done here?
<TabAtkins> dbaron: larger answer is that we need a spec to centralize a bunch of this
<TabAtkins> dbaron: part of reason for all these questions about CBs and stacking contexts, etc are such a mess is that there are multiple specs amending dfns that don't actually exist.
<TabAtkins> dbaron: So someone needs to write a spec that defines these terms.
<TabAtkins> dbaron: So opacity/mix-blend-mode/etc can all hook that instead of defining ad-hoc
<TabAtkins> dbaron: simple thing is to resolve that <fO> establishes a containing block for abpos and fixpos
<TabAtkins> flackr: I think sticky says it moves according ot th enearest ancestor with nonvisible overflow
<TabAtkins> dbaron: Can <fO> overflow...?
<TabAtkins> AmeliaBR: Haven't tested
<TabAtkins> AmeliaBR: I think it overflows, I've done it to get a <label>.
<TabAtkins> astearns: Let's resolve on abpos/fixpos and do sticky separately?
<TabAtkins> chris: Rossen wanted it to be an ICB...?
<TabAtkins> hober: Without him explaining why, I'm loathe to define that
<TabAtkins> iank_: Yeah, ICB has a lot of other implications.
<TabAtkins> AmeliaBR: I can take action on edits
<TabAtkins> TabAtkins: Ping me and elika for review
<TabAtkins> astearns: proposed resolution: svg spec says that <fO> creates a containing block for fixpos and abspos children
<TabAtkins> RESOLVED: svg spec says that <fO> creates a containing block for fixpos and abspos children

@dbaron
Copy link
Member Author

dbaron commented Jun 6, 2019

... and we still need to follow up about whether position: sticky requires that we say something about overflow or similar, and also whether <foreignObject> should be an "initial containing block".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants