[csswg-drafts] [css-positioning] position: popover proposal (#5699)

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

== [css-positioning] position: popover proposal ==
As a custom element author, it's not uncommon to create an element that utilizes some sort of dynamic "popover." There are many examples of this, but a few common ones include:

- Dialogs
- Dropdowns
- Combo boxes
- Tooltips

In most cases, such components require a "panel" element that "pops over" the page content. The problem is the panel is subject to containment by its ancestors. For example, a containing `<div>` with `overflow: hidden` will [correctly] cause unwanted clipping.

![CleanShot 2020-11-05 at 09 20 46](https://user-images.githubusercontent.com/55639/98252789-50490080-1f48-11eb-8359-b6d370233c68.gif)

Traditional workarounds for this problem include:

- "Hoisting" the panel element to another position in the DOM (e.g. before `</body>`)
- Using a fixed position strategy to "break out" of the containing element

Neither of these solutions are elegant, nor do they guarantee the panel will be positioned as intended. The former relies on DOM modifications and arbitrary z-indexes while the latter requires that no ancestors have `transform`, `perspective`, or `filter` properties:

> It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. [Source](https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed)

In the world of web components, particularly when a shadow root is attached, the panel is commonly contained in the shadow root. As a result, it cannot be "hoisted" to another location in the DOM because its styles are encapsulated and slotted content will no longer work. Hoisting also makes accessibility difficult since `id` attributes can no longer be referenced once they're removed from the shadow root (not to mention potential conflicts with ids in the global scope). This leaves us with only one option — the fixed position strategy.

With the fixed position strategy, there's no way to guarantee a panel's position. You can try to identify its containing block by traversing the DOM and checking for relevant properties, but that's arduous. And if the containing block isn't viewport, "fixing it" will involve altering properties that may cause visible changes to unrelated ancestors.

## The Proposal

I suspect this use case will become more and more common as web components become ubiquitous. After many weeks of experimentation, I've come to the conclusion that this could better be solved at the CSS level. Therefore, I would like to propose a new position property:

.my-panel {
  position: popover;

Just like `position: fixed`, an element with `position: popover` will be removed from the normal document flow, and no space is created for the element in the page layout. Unlike `fixed`, the element will be positioned relative to the viewport, not its containing block. This makes sense since popovers are pseudo-modal and seldom appear off-screen.

And since naming is hard, a few alternatives might be `position: overlay`, `position: anchored`,  or `position: viewport`.

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

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

Received on Thursday, 5 November 2020 14:59:53 UTC