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

Interaction between Popover API and CSS Anchor Positioning specs #9311

Closed
jpzwarte opened this issue May 19, 2023 · 6 comments
Closed

Interaction between Popover API and CSS Anchor Positioning specs #9311

jpzwarte opened this issue May 19, 2023 · 6 comments
Labels
topic: popover The popover attribute and friends

Comments

@jpzwarte
Copy link

So I've been reading efforts on popover and CSS Anchor positioning. Based on my understanding, i wrote out some scenarios on how I think this will/should work. This includes imperative & declarative ways to show a popover.

If this is how it will work based on current specs, then great, consider this a thought exercise :) If not, please point out where I've gone wrong and we can discuss that.

1. Imperative popover without invoker

document.querySelector('button').addEventListener('click', () => {
  document.querySelector('#popover').togglePopover();
});
<button>Button</button>
<div id="popover" popover></div>

No anchorElement or anchor attribute is set. The popover is centered in the viewport because there is no CSS anchor positioning styling.

2. Imperative popover with invoker

This references #9111 for the invoker parameter.

document.querySelector('button').addEventListener('click', event => {
  document.querySelector('#popover').togglePopover({ invoker: event.target });
});
<button>Button</button>
<div id="popover" popover></div>

Implicitly sets the anchorElement to the button, based on the invoker parameter to togglePopover. The popover is centered in the viewport because there is no CSS anchor positioning styling.

3. Declarative popover without anchor attribute

<button popovertarget="popover">Button</button>
<div id="popover" popover></div>

Implicitly sets the anchorElement property to the button. The popover is centered in the viewport because there is no CSS anchor positioning styling.

4. Declarative popover with anchor attribute

<button id="button" popovertarget="popover">Button</button>
<div id="popover" anchor="button" popover></div>

The anchor attribute causes anchorElement to be set on the popover. The popover is centered in the viewport because there is no CSS anchor positioning styling.

5. Declarative popover without anchor attribute and CSS anchor positioning styling

<style>
  #popover {
    position: absolute;
    top: calc(.5em + anchor(auto));
  }
</style>
<button popovertarget="popover">Button</button>
<div id="popover" popover></div>

The anchorElement is set implicitly on the popover and has the value of the button element. Based on the anchorElement, the button automatically becomes the implicit anchor element of the popover (see https://drafts.csswg.org/css-anchor-position-1/#anchor-pos). The popover is positioned relative to the button because of the CSS anchor positioning styling.

6. Declarative popover with anchor attribute and CSS anchor positioning styling

<div id="other"></div>
<style>
  #popover {
    position: absolute;
    top: calc(.5em + anchor(auto));
  }
</style>
<button popovertarget="popover">Button</button>
<div id="popover" anchor="other" popover></div>

The anchor attribute causes the anchorElement property to be set on the popover and has the value of the div#other element. Based on the anchorElement, thediv#other element automatically becomes the implicit anchor element of the popover. The popover is positioned relative to div#other because of the CSS anchor positioning styling.

7. Declarative popover with CSS anchor positioning styling anchor-element override

<div id="decoy"></div>
<div id="other"></div>
<style>
  #other {
    anchor-name: --other;
  }
  #popover {
    position: absolute;
    top: calc(.5em + anchor(--other auto));
  }
</style>
<button popovertarget="popover">Button</button>
<div id="popover" anchor="decoy" popover></div>

The anchor attribute causes the anchorElement property to be set on the popover and has the value of the div#decoy element. Because the popover has an explicit anchor element specified in the anchor() function, the popover is positioned relative to div#other.

@jpzwarte jpzwarte mentioned this issue May 19, 2023
4 tasks
@jpzwarte
Copy link
Author

Is there an 8th scenario where anchorElement is set implicitly by the CSS anchor-element parameter? cc @josepharhar

@nt1m nt1m added the topic: popover The popover attribute and friends label May 22, 2023
@josepharhar
Copy link
Contributor

I made all of the cases into a jsfiddle here: https://jsfiddle.net/jarhar/301cmbqo/
I tested it using chrome canary with experimental web platform features enabled:
https://www.google.com/chrome/canary/
chrome://flags/#enable-experimental-web-platform-features

It looks like anchor positioning and anchorElement is only enabled when the anchor attribute is set, which goes against your scenarios 2, 3, 5, and 7.
I'm not sure if this is the long term plan or not. @xiaochengh @mfreed7

@xiaochengh
Copy link
Contributor

Right now there's no such thing as "anchorElement is implicitly set". It has to be explicitly set via anchor attr or anchorElement property.

It will also look a bit broken to me if any popover attr implicitly sets anchorElement, because we are trying to add anchorElement as a standalone HTML feature, not part of popover.

It's possible that we make popovers somehow have an implicit anchor element (eg invoker); that's going to be a different story though

And auto anchor positioning (anchor(auto)) isn't implemented yet so those demos may not work as expected.

Is there an 8th scenario where anchorElement is set implicitly by the CSS anchor-element parameter?

There's no CSS setting the anchorElement property. And there shouldn't be, because (normally) it should be CSS that depends on DOM, not the other way around.

@jpzwarte
Copy link
Author

It's possible that we make popovers somehow have an implicit anchor element (eg invoker); that's going to be a different story though

Right, so I can understand not having anchorElement "magically" be set by the popovertarget attribute on the invoker. As a web developer though I'm specifically interested in the implicit anchor element pointing to the popovertarget invoker. That would save me from having to point them at each other using DOM ids (popovertarget="popover" and anchor="button"). Most of my use cases for popovers are where the invoker is also the anchor element. So when building apps, this would really help.

Also in the 1-n scenario (1 popover and n invokers), this would also save me from having to write javascript to set the anchorElement to the invoker.

@mfreed7
Copy link
Contributor

mfreed7 commented May 26, 2023

I agree with the comments above that we shouldn't mix the invoker and the anchor. It's possible that we could decide to make the invoking element an "implicit anchor element" but there's a separate question about whether we need to expose that implicit anchor element as a Javascript property.

Note that in all of your imperative examples in the OP, you can use popover.anchorElement = invokingElement and things should work. In the declarative examples, since they're declarative, the "right" way to do this is just to add <div popover anchor=anchor-id>.

@josepharhar
Copy link
Contributor

As your questions have been answered, and the suggestion of automatically making the invoker an anchor is being handled here, I'm going to close this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: popover The popover attribute and friends
Development

No branches or pull requests

5 participants