8000 [css-positioning] position: popover proposal · Issue #5699 · w3c/csswg-drafts · GitHub
[go: up one dir, main page]

Skip to content

[css-positioning] position: popover proposal #5699

@claviska

Description

@claviska

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

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

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.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      0