[css-anchor-position] "slide" an element to keep it in its IMCB · Issue #9960 · w3c/csswg-drafts (original) (raw)
(This has been discussed a bit in the past, but I think it would benefit from a fresh issue so it can be discussed in the context of the current spec design.)
It's fairly common in JS-backed anchoring to have the popup be positioned in a particular way relative to the anchor by default, but if that would cause the popup to overflow, to "slide" the popup off of its preferred alignment to stay on screen.
For example, that's how the popup panels work in Bikeshed-generated specs - by default they're effectively inset-area: bottom center-right
, but if the panel would go off-screen, it slides to the left to stay visible.
You can't easily do this with insets, due to the rules about overconstrained sizes. For example, reproducing Bikeshed's panels might look like:
.dfn-panel { position: fixed; anchor-default: --dfn; top: anchor(bottom); left: anchor(left); width: 300px; right: 0; }
This tries to prevent the right edge from going past the edge of the viewport, but now it's overconstrained since left+width+right are all specified. We end up ignoring right
entirely. :(
So there's a few possible ways to handle this.
I think the easiest would be to just hook into the anchor-center alignment - allow saying justify-content: anchor-center shiftable
, and this (a) turns off the automatic reduction in available space to be the largest centered length that fits, and (b) shifts it off of being anchor-centered if that helps it stay visible.
This limits us to just getting the effect on anchor-center, tho, which would prevent Bikeshed specs from using it without changing its design. We could potentially accompany this with more anchor-specific alignment values, like anchor-start
and anchor-end
, that give the right/left-biased alignment. So Bikeshed would use inset-area: bottom; justify-self: anchor-start shiftable;
.
Another option would be to address this at the insets level, with some way to specify a minimum inset which is respected at a stronger level than the existing overconstrained rules. Like:
.dfn-panel { top: anchor(bottom); left: anchor(left); width: 300px; right: min 0; /* ??? */ }
This would make the right
index act as auto by default, but if the right edge would go below 0, it gets clamped to 0, and left
is overridden instead.
I'm inclined against this somewhat, as it doesn't interact with anchor-center in any meaningful way (and reproducing anchor-center behavior via insets is possible, but relatively difficult). Using insets like this can also clash with attempts to use the IMCB for overflow control.
So my concrete suggestion is:
- Add
anchor-start
andanchor-end
values to the self-alignment properties, which line up your start edge to your anchor's start edge, or end to end. - Add an optional keyword to the
anchor-*
values that indicates the alignment is shiftable, if necessary to avoid overflowing the IMCB.
The shiftability is limited to keep the abspos still visibly attached to the anchor even if the anchor leaves the IMCB entirely; basically you're allowed to shift until you hit what anchor-start
or anchor-end
(as appropriate) would produce.