tabatkins / specs

:pencil: Spec proposals that aren't yet approved by the relevant Working Group.
179 stars 22 forks source link

[css-anchor-position] Sizing popups relative to anchor _and_ viewport bounds #79

Closed jelbourn closed 2 years ago

jelbourn commented 2 years ago

In the Angular ecosystem, we have a module, @angular/cdk/overlay, that deals with this popup problem space. Relevant positioning code, development demo.

One key feature of our code here is that we can control the size of the popup based on the amount of space available in the viewport. This is important for uses cases involving long menus/comboboxes, where you want the popup to be as large as possible without extending beyond the bounds of the viewport. At the same time, if the content of the popup is smaller, it naturally fits those contents:

A popup with 100 items takes up all available space between the anchor and the viewport boundary: image

While a popup with 5 items naturally fits its content: image

From reading the draft spec, it seems like there's a way to size the popup relative to the size of the anchor, but it's not clear to me if you could accomplish this behavior that ties to the viewport bounds.

jelbourn commented 2 years ago

Think about this more- would something roughly like this work if the anchor-size function were changed to support inset properties?

.panel {
  top: anchor(origin, bottom);
  max-height: calc(100vh - anchor-size(origin, bottom));
}
tabatkins commented 2 years ago

Make the anchored element fixpos, and 0%/100% correspond to the viewport edges, while anchor() can correspond to whatever element you're caring about.

("Make it fixpos" is the solution to most anchoring problems, I believe.)

In this case, you'd do:

.panel {
  top: anchor(--origin bottom);
  bottom: 100%;
  align-self: start;
  max-height: 100%;
}

That is, set up your inset-modified containing block (IMCB) to start at the bottom of the --origin element and extend to the bottom of the screen, set a max-height of at most that full distance, and use align-self to align it to the top of the IMCB when it's shorter than that.

jelbourn commented 2 years ago

@tabatkins wouldn't setting bottom: 100% always make the popup extend to the viewport boundary, rather than only when the content would be large enough to warrant it?

tabatkins commented 2 years ago

If done by itself, yes; that's what the align-self: start is there for. It changes the behavior of abspos from "stretch between both explicitly-set edges" (today's default) to "auto-size, then align within the rectangle defined by the edges".

(That's per spec, at least. Browsers haven't caught up to the spec in this regard yet, but will. Chrome might do it later this year (tho no promises on timeline).)