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-anchor-position] "slide" an element to keep it in its IMCB #9960

Open
tabatkins opened this issue Feb 14, 2024 · 3 comments
Open

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

tabatkins opened this issue Feb 14, 2024 · 3 comments

Comments

@tabatkins
Copy link
Member

(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:

  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.

@una
Copy link
Contributor

una commented Feb 14, 2024

Because I think visuals are useful, here is a demo of the current behavior:

Kapture 2024-02-14 at 15 11 35

This is the desired behavior: keeping this element within the containing block (shift it within the containing block) before squeezing to fit into the inset area.

Screenshot 2024-02-14 at 3 21 50 PM

Screenshot 2024-02-14 at 3 09 24 PM

@tabatkins
Copy link
Member Author

@fantasai has said she wants to put more serious thought into this to explore the space before she agrees to anything (and her expressed doubts seem reasonable to me), so I propose we handle this in level 2. The idea presented in this thread, as well as any potential alternate approach I can think of (min/max insets, a more explicit "slide me" value or property) are all compatible with being added in the future.

@yisibl
Copy link
Contributor

yisibl commented Apr 10, 2024

This seems to be a very common use case, currently, we can simulate this behavior to some extent with inset-area, but there is a jitter.

Demo: https://codepen.io/yisi/pen/yLrjKEO

2024-04-10.17-00-38.mp4

But this does not work if the popover width is greater than or equal to the viewport width.

image

tabatkins added a commit that referenced this issue May 29, 2024
…to stay in the original containing block' behavior, and revert the anchor-center 'shrink the available space' behavior. #10316 #10315 #9960
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

5 participants