Open tabatkins opened 1 month ago
If we don't do this, then to avoid the alignment badness in my example, I think we have to change the default alignment to be unsafe in all cases when the CB is the ICB or a scroller. This means that you'll overflow if you're very close to the top or bottom of the content, but you'll get reasonable alignment in all other cases.
Accepting this change means we can keep the medium-safety alignment, as we'll get correct alignment by default in these cases, and can still shift to avoid overflow when the anchor is very close to the top or bottom.
The CSS Working Group just discussed [css-align][css-position][css-anchor-position] Introduce "document containing block" for some purposes?
, and agreed to the following:
RESOLVED: Adopt the concept of document containing block (better name TBD) into position-4 and have anchor positioning use it by default instead of ICB
RESOLVED: Publish FPWD of position-4
All right, defined. @fantasai and/or @frivoal , mind reviewing?
I went with "scrollable containing block" as the name, since "document containing block" was bad.
[another continuation from #10859]
(Apologies for the length of this, there's a lot of context needed to make it understandable. There's a "Proposal" heading further down if you wanna just skip to the idea first.)
Anchor Positioning, in general, makes the actual bounds of the abspos containing block much more important than they used to be. This isn't a huge deal if the CB is generated by an element, or is the viewport - both produce meaningful rectangles with relevant sizes and positions. But I keep running into issues when the CB is the ICB.
The ICB's size is reasonable - it's the size of the viewport, which is perfectly fine as a default available space for the abspos, often actually good. It's the ICB's position that's nonsensical for many purposes - it lives at the top of the document, aligned with 0,0 in the root scroller. On most pages, then, the position of most elements is completely outside of the ICB, meaning that for things which care about the relative position of the CB and an anchor element (such as
position-area
), you get annoying, meaningless interactions way more often than in the other cases.For example, if you use
position-area: bottom
, your IMCB is the space between your anchor's bottom edge and the CB's bottom edge. If your CB is the ICB, and your element is somewhere further down the page, then these two edges are in the wrong order, and produce a negative-height rectangle. Anchor Pos handles this fairly gracefully, and causes the "CB bottom" edge to be "pulled down" by the anchor-bottom edge, so we get a zero-height IMCB flush with the anchor's bottom, but that's still not a useful IMCB. You immediately overflow, for example, which triggers fallback positioning.What you actually want in this case, I think approximately 100% of the time, is a CB that is "the height of the document". That is, if your anchor is in the very last paragraph, very close to the bottom of the document, you expect your available space to be small and maybe trigger fallback positioning; but if your anchor is in the middle of the document, you expect there to be ample space below you.
As an example of how wrong the current behavior goes, imagine a normal document, like a spec, full of multiple screenfulls of text. An anchor element is right in the middle of the document, well outside the initial viewport, but with thousands of pixels open above and below it. An abspos anchors to it, and uses
position-area: right;
, getting a default vertical alignment ofanchor-center
.The actual IMCB for this element stretches from the top edge of the document (the top of the ICB), down to the bottom edge of the anchor element. (It wants to stretch to the bottom of the ICB, but that's way up top, well above the anchor, so the anchor drags the line down to its own bottom edge.) Now, the default alignment safety kicks in - if the abspos is taller than the anchor, centering it would overflow the IMCB, so it shifts upward until its bottom edge is flush with the anchor's bottom edge.
This shifting only happens if the anchor is initially offscreen. If the anchor is initially on screen, "above the fold", then it sees plenty of room above and below it, and centers properly. But, because the anchor is initially well outside the bounds of the ICB, the IMCB is artificially shrunken on one side, and the "centered" element is now permanently frozen in an un-centered position.
(Note that it does not correct itself if you scroll down so the element is on the screen! None of its edges or coordinates care about the current scroll offset; it's an abspos. It's just weirdly off-center because it was initially off-screen, and it stays weirdly off-center permanently.)
Even outside of Anchor Positioning, it's not unusual for people to want to abspos something to the bottom/right of "the content", either on the root scroller or within a scrollable element. This currently isn't possible directly - you have to use a wrapper relpos inside the scroller. If the abspos uses the scroller itself as its abspos containing block, it gets the equivalent of the ICB - a rectangle the size of the scrollport, positioned at the origin.
Proposal
We define a new default containing block, the "scrolling content block". This is, roughly, the height of the document. I talked this over with @bfgeek and the best option he knows of that's currently available and won't require adding memory to every element is the "interior padding edge", aka the size of a wrapping div around the content. This ignores other absposes, and transforms, both of which do affect the "scrollable overflow rect" and which we don't want, both for cyclic and compositing reasons.
Anything using the "scrolling content block" as its CB still gets an available space that's the size of the scrollport, so a
100%
width or height is still reasonably sized. But its bounds for positioning purposes is larger.When using
position-area
, in any situation where the abspos would today use the ICB as its containing block, or a scrollable element as its containing block, it instead uses the "scrolling content block".Separately, we figure out some way to expose this to normal positioned elements, too. Possibly a sub-property of
position
. Until then, authors can hack it by usingposition-area: all
with any validposition-anchor
, even if they're not actually using anchor positioning for anything.The definition for "scrolling content block" above, notably, doesn't make things any better when people are using "fake root scrollers", aka setting
html { height: 100%; overflow: auto; }
. The definition I gave will then tightly wrap around thehtml
element, resulting in a rect more or less identical to the ICB. This isn't great, but it's exactly the situation we're in today for every element. So we'll still be in a better situation for most things, and no worse of a situation for these things in particular. If @flackr ever revives his idea of allowing other elements to provide the root scroller, that'll fix this issue as well.