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

[css-position] Static position of abspos top layer elements inside fixed pos. #9939

Open
emilio opened this issue Feb 13, 2024 · 16 comments
Open

Comments

@emilio
Copy link
Collaborator

emilio commented Feb 13, 2024

This is the cyclic / ordering issue that I was concerned about in #8040.

Both Firefox and Blink get it wrong. WebKit gets it right, but I'm not sure what they're doing, maybe they're laying out the abspos twice?

<!DOCTYPE html>
<meta charset="utf-8">
<style>
#outer {
  position: fixed;
  width: 200px;
  height: 200px;
  border: 2px solid blue;
}
dialog {
  display: inline;
  position: absolute;
  inset: auto;
}
</style>
Some content.
<br>
<br>
<br>
<br>
<br>
Some more.
<br>
<div id=outer>
  Fixed-pos.
  <dialog>Absolute popover inside fixed element</dialog>
</div>
<script>
  document.querySelector("dialog").showModal();
</script>

The main issue here is that you have:

  • Viewport box
    • ICB
      • Abspos
    • Fixedpos

So you lay out the abspos before the fixedpos, and the static position isn't computed yet.

cc @rlbuis @bfgeek @chrishtr

@emilio emilio added the Agenda+ label Feb 13, 2024
@tabatkins
Copy link
Member

My preferred fix for this, fwiw, is that when an element is top-layer'd, it loses its static position. (We default it to 0,0 or something equally trivial.) We have Anchor Position now, there's no need to continue twisting ourselves into knots to maintain this clunky static-pos behavior in weird cases.

This would kill the cyclic problem in all permutations of this issue.

@emilio
Copy link
Collaborator Author

emilio commented Feb 13, 2024

@rwlbuis do you know what WebKit is doing here?

@rwlbuis
Copy link

rwlbuis commented Feb 14, 2024

@rwlbuis do you know what WebKit is doing here?

Tim is more an expert here.

@nt1m
Copy link
Member

nt1m commented Feb 14, 2024

@emilio Not sure this answers your question, but here's where we implemented the containing block adjustments:

WebKit/WebKit@4f453d4
WebKit/WebKit@9dffcf6

@emilio
Copy link
Collaborator Author

emilio commented Feb 14, 2024

@nt1m so webkit parents all top layer elements (abspos and fixed pos) to the viewport rather than the root scroller? Isn't that incorrect?

@emilio emilio added the css-position-3 Current Work label Feb 19, 2024
@chrishtr
Copy link
Contributor

I agree that Chrome appears to render this example wrong (I made the example into a jsbin here). What's wrong about it is that it has an incorrect static position that includes the content under the ICB ("some content", a few <br>s, and "some more"). Since the containing block of the abspos element is the viewport in this case, those should not contribute to its static position.

It looks like one can see the bug more clearly in this demo which uses position:relative and top:10px, which positions correctly in Chrome. Before adding top:10px the static position is also wrong, but after adding top:10px it renders correctly in Chrome.

Perhaps there is an issue with circularity, or at least extra complications, in computing static positions correctly in cases like this, though I think it's just a straight-up bug in Chrome that I think could be fixed by computing static positions separately in the top layer. @bfgeek WDYT?

@emilio
Copy link
Collaborator Author

emilio commented May 10, 2024

I think could be fixed by computing static positions separately in the top layer.

Not sure about that. You can have this case (abspos element in the top layer depending on fixed pos not in the top layer), but you can also trivially have the opposite. Also, you can have an abspos in the top layer depend on a fixed pos in the top layer and vice versa too, right?

@chrishtr
Copy link
Contributor

You can have this case (abspos element in the top layer depending on fixed pos not in the top layer),

It doesn't depend on it though, right? Which is achieved by reparenting its box in the layout tree.

but you can also trivially have the opposite. Also, you can have an abspos in the top layer depend on a fixed pos in the top layer and vice versa too, right?

I don't think there should be any layout dependency. The top layer should be completely independent of the ICB and its descendants.

@emilio
Copy link
Collaborator Author

emilio commented May 11, 2024

Well that's what this issue is about. The dependency comes from the static position, because that is usually "the position the box would have if not abspos" (and thus if not in the top layer).

@chrishtr
Copy link
Contributor

Update: looks like it actually renders correctly in Chrome. It pushes down the static position because the top layer is a sibling of the HTML element in the layout tree. Here's an example with an artifically larger HTML element (see red rectangle).

Note: in a few times while making that demo I observed wrong static positioning for the top layer element, which seems like a race condition in Chromium. @bfgeek says he might know what caused that, but it's an implementation caching bug, not a spec issue.

@emilio
Copy link
Collaborator Author

emilio commented May 22, 2024

I'm confused, so in chrome the top-layer reparenting also reparents the regular in-flow position? That is... not what I'd expect...

I mean, that makes the static position rather useless I guess, but that means that we have some leeway here and @tabatkins's proposal (making top layer elements just lose its static position) shouldn't be a webcompat issue (which is something that I feared initially).

@chrishtr
Copy link
Contributor

I'm confused, so in chrome the top-layer reparenting also reparents the regular in-flow position? That is... not what I'd expect...

What do you mean by "reparents the regular in-flow position"? Not sure what you're saying..

@emilio
Copy link
Collaborator Author

emilio commented May 23, 2024

Basically that the static position doesn't reflect the position the element would have if not top layered (which is what WebKit and Gecko do). It moves the static position to after the html element.

@chrishtr
Copy link
Contributor

It moves the static position to after the html element.

Ok thanks for explaining.

That's correct, but it's what I would expect. Why would you want the static position to reflect the position it would have if not top layered? It shouldn't retain such positioning right? Because the top layer is defined to reparent and relayout in full...

@astearns astearns closed this as completed by moving to Wednesday morning in CSSWG June 2024 meeting Jun 3, 2024
@astearns astearns reopened this Jun 3, 2024
@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-position] Static position of abspos top layer elements inside fixed pos., and agreed to the following:

  • RESOLVED: Make the static position of top layer boxes not depend on the size or position of any other element on the page, likely by making static position rectangle the ICB
The full IRC log of that discussion <TabAtkins> relative static position of absolute positions, fixed
<fantasai> emilio: This is the case where the static position of the abspos that depends on something laid out after it
<fantasai> emilio: annoying because cyclic
<fantasai> emilio: it seems what Blink does is making the static position at the end of the HTML element or something?
<fantasai> emilio: so mostly ignored
<fantasai> emilio: Gecko [missed]
<fantasai> emilio: And WebKit does something else that's incorrect
<fantasai> emilio: Tab's proposal is to ignore static position in top layer
<fantasai> iank_: I believe what happens is we reparent the top layer boxes in the box tree
<fantasai> iank_: so it's a box tree construction effect, not a layout effect
<fantasai> emilio: Conceptually they're reparented anyway because abspos
<fantasai> iank_: Blink doesn't have the concept of a static positoin placeholder like Gecko does
<fantasai> iank_: so as if you moved the placeholder and the thing during box tree insertion
<fantasai> emilio: Think it's best to ignore the static position
<fantasai> iank_: I think we've defined it to be, this happens at box tree time
<fantasai> iank_: or is it defined as something not that?
<fantasai> emilio: in Gecko we have two boxes for this element
<fantasai> emilio: but conceptually the abspos box (primary box) does get reparented
<fantasai> emilio: the static position, conceptually to me, is the position it would have if it wasn't abspos and thus not in top layer
<fantasai> iank_: but if this gets reparented during box tree...
<fantasai> iank_: when you insert abspos into tree in Blink, we don't reparent to the containing block. It sits whereever it lives
<futhark> q+
<fantasai> emilio: but it gets laid out and painted in a different order
<fantasai> emilio: behavior Blink has is super weird, so prefer to ignore it
<fantasai> iank_: you could just reparent the static position box to the same place?
<fantasai> emilio: yeah but I think it's super weird
<fantasai> iank_: but that's what the spec says?
<fantasai> emilio: I think that depends on whether the spec meant to include the static pos
<fantasai> iank_: staticpos is spec fiction
<miriam> ack futhark
<fantasai> futhark: Spec currently says "rather than generating boxes as usual, generate boxes as sibling of root element"
<fantasai> futhark: so spec says what we do
<fantasai> futhark: if that's not what we want, then we need to change the spec
<fantasai> emilio: I'm not opposed to close no change and test+clarification in the spec but... it does feel a little unusual
<fantasai> emilio: idk if that would cause issues, because then when destroying boxes you cannot reach ... if you remove an element in the DOM, can't reach descendant elements that are top layer
<fantasai> emilio: prefer to behave as regular abspos, parented to the relevant containing block
<fantasai> emilio: I'm fine with either behavior
<emeyer> fantasai: Could someone describe the situation that crfeates a cycle?
<emeyer> s/crfeates/creates/
<emeyer> fantasai: The top layer escapes the fixedpos to go into the top layer?
<emeyer> emilio: Right.
<miriam> ack fantasai
<emeyer> fantasai: Why is the top layer element not asbpos?
<emeyer> emilio: Top-layer things escape their usual containing block rules
<emeyer> iank_: Right, they get lumped on the end of the list for the ICB
<emeyer> iank_: The difference at the moment is Gecko doesn't do this well
<emeyer> iank_: In Gecko the placeholder isn't reparented so you need to lay out a second level of top layer thing to get the correct static position
<emeyer> fantasai: They're both top layer?
<emeyer> iank_: They're both direct descendants of the ICB
<emeyer> fantasai: I agree with Emilio it's super weird to reparent them and have them at the end of the static HTML element
<emeyer> fantasai: I suspect what the spec meant is similar to what happens with fixed position
<emeyer> fantasai: They wanted to make sure it would be painted on top
<emeyer> iank_: Pulling into a separate list at the ICB level achieves what's needed
<emeyer> fantasai: Yeah, the answer is just very weird
<futhark> q+
<emeyer> …I agree with Emilio that the static position of the element being at the end of the HTML element is super weird even if that's easy or what the spec currently says
<miriam> ack futhark
<fantasai> s/super weird/super weird from an author's PoV/
<emilio> https://drafts.csswg.org/css-position-4/#top-styling
<emilio> > Unless overridden by another specification, its static position for left, right, and top is zero.
<emeyer> futhark: In section 3.1 in CSS-position-4, there's a list on top layer styling that the static position for left, right, and top is 0.
<emeyer> TabAtkins: I guarantee I forgot to list out all four
<emeyer> fantasai: I don't know how much review this rewrite has gotten
<emilio> Comes from https://github.com/w3c/csswg-drafts/commit/051d37a64ca714fa0238df6db019967de2a086dd fwiw
<emeyer> fantasai: I'm not sure how much reliance I'd put on the validity of the spec since it was copied over from another spec
<emeyer> TabAtkins: Since top layer is new, we probably don't have a lot in the way of meaningful compatibility troubles
<fantasai> s/another spec/another spec drafted by someone who isn't a CSS layout spec expert/
<emeyer> …So let's just do the simplest possible thing!
<emeyer> …Which is 0,0 static position
<emeyer> iank_: With a zero-width-height static position?
<emeyer> TabAtkins: The concept of static position doesn't exist and everything resolves to zero
<emeyer> iank_: You don't want everything to resolve to zero
<emeyer> TabAtkins: Why not?
<emeyer> iank_: I think you actually just want the static position at 0,0
<emeyer> TabAtkins: I don't understand the objection
<emeyer> iank_: Anchor position sets the alignment differently and strethces
<emeyer> TabAtkins: Oh, yes, we probably want to fix that to not stretch
<emeyer> iank_: Other elements don't support alignment
<emeyer> TabAtkins: If we set it to 0,0 in the corner we don't get the auto-alignment, which we wanted to avoid in anchor positioning
<emeyer> …For legacy reasons, we can't get away with that in abspos
<emeyer> iank_: I think in UA styles, all these things have been set to zero anyway
<emeyer> …Like, you have to set insets to trigger this behavior, right?
<emeyer> emilio: For popover, I think so, but I'm not sure about other things
<emeyer> iank_: I'm fine with saying that static positioning is zeroed out
<emeyer> fantasai: Is that going to make sense for non-fixed-position cases like top layer elements that are halfway down the page?
<emeyer> iank_: Reparenting in the box tree up to the very top, when would that trigger?
<emeyer> fantasai: You scroll halfway down the page and you click on something that's in the top layer
<emeyer> …If it's fixedpos and not in the viewport you can't read the whole thing
<emeyer> …Sometimes it gets pushed into a static position, which makes it scrollable
<emeyer> TabAtkins: The generic answer is, if you want to attach to a thing on the page, use anchor positioning
<emeyer> …We don't need to rely on fixed things that are weird if we have a more powerful variant
<emeyer> (awkward silence)
<emeyer> miriam: I don't feel a need to preserve static positioning generally, and especially not going into the top layer
<emeyer> TabAtkins: Can we just say that then?
<emeyer> …If you're top layer, we do the same as anchor positioning?
<emeyer> fantasai: I think what makes more sense is to define the static position rectangle in the ICB, which I think gives you the right effects
<emeyer> TabAtkins: I don't see why it would, necessarily
<emeyer> …There'd be no connection to its normal position in the DOM
<emeyer> fantasai: I think we want to define the rectangle where it lives and define what that means
<emeyer> …If you set everything to zero then it will anchor to that edge
<emeyer> …We should talk about it offline
<emeyer> TabAtkins: Ah, I see what you mean
<emeyer> …We can resolve on doing something arbitrary
<emeyer> fantasai: Propose to make the static position of the top layer does not depend on the size or position of any other element on the page
<fantasai> fantasai: And probably define by making staticpos rectangle as ICB
<emeyer> miriam: Do we have a thing we can resolve on?
<fantasai> PROPOSED: Make the static position of top layer boxes not depend on the size or position of any other element on the page, likely by making static position rectangle the ICB
<emilio> sgtm
<emeyer> miriam: Any objections?
<fantasai> RESOLVED: Make the static position of top layer boxes not depend on the size or position of any other element on the page, likely by making static position rectangle the ICB
<RRSAgent> I have made the request to generate https://www.w3.org/2024/06/11-css-minutes.html fantasai
<jarhar> scribenick: jarhar

@fantasai
Copy link
Collaborator

fantasai commented Aug 9, 2024

@emilio I put in some minimal edits to define the ICB as the static position rectangle for top layer elements. Is there anything else you think needs clarification here? https://drafts.csswg.org/css-position/#staticpos-rect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Tuesday afternoon
Development

No branches or pull requests

8 participants