[csswg-drafts] [css-anchor-position] "slide" an element to keep it in its IMCB (#9960)

tabatkins has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-anchor-position] "slide" an element to keep it in its IMCB ==
(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:

```css
.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:

```css
.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:

1. Add `anchor-start` and `anchor-end` values to the self-alignment properties, which line up your start edge to your anchor's start edge, or end to end.
2. 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.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/9960 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Wednesday, 14 February 2024 20:03:28 UTC