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

Add anchor attribute #9144

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open

Add anchor attribute #9144

wants to merge 35 commits into from

Conversation

josepharhar
Copy link
Contributor

@josepharhar josepharhar commented Apr 10, 2023

The anchor attribute can be used to set up CSS anchor positioning by setting an implicit anchor element: https://drafts.csswg.org/css-anchor-1/#implicit-anchor-element.

The CSS properties used to set up anchor positioning relationships are perfect for repeating patterns, such as:

<div class=anchor></div>
<div class=positioned></div>
<div class=anchor></div>
<div class=positioned></div>
<div class=anchor></div>
<div class=positioned></div>
<style>
  .anchor { anchor-name: --foo; }
  .positioned { position-anchor: --foo; }
</style>

However, for structural patterns, such as when using a Popover, an HTML attribute has less boilerplate and makes the relationship much more directly observable:

<button id=button1>Pick something #1</button>
<div popover anchor=button1>Popover for button1</div>

This structural pattern can apply to other use cases also, where unique elements are paired.

When used with the Popover API, the anchor attribute also naturally helps to create a relationship that ensures popovers are properly nested:

<button id=button>Menu 1</button>
<menu popover anchor=button>
  <li id=item1>Item 1</li>
  <li id=item2>Item 2</li>
</menu>
<menu popover=hint anchor=item1>
  Helpful tooltip about item 1
</menu>
<menu popover=hint anchor=item2>
  Helpful tooltip about item 2
</menu>

This PR adds the anchor attribute to HTML and connects it to the Popover API.


/dom.html ( diff )
/index.html ( diff )
/indices.html ( diff )
/infrastructure.html ( diff )
/popover.html ( diff )
/references.html ( diff )
/rendering.html ( diff )

The anchor attribute can be used to set up CSS anchor positioning by
setting an implicit anchor element:
https://drafts.csswg.org/css-anchor-1/#implicit-anchor-element
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Apr 17, 2023
This patch also adds WPTs for the anchor attribute (without popovers)
to support the HTML PR whatwg/html#9144

Fixed: 1432016
Change-Id: I3e80326268008e6beaf74389bb32c01050406a81
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Apr 17, 2023
This patch also adds WPTs for the anchor attribute (without popovers)
to support the HTML PR whatwg/html#9144

Fixed: 1432016
Change-Id: I3e80326268008e6beaf74389bb32c01050406a81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4434155
Commit-Queue: Joey Arhar <[email protected]>
Commit-Queue: Xiaocheng Hu <[email protected]>
Reviewed-by: Joey Arhar <[email protected]>
Code-Coverage: Findit <[email protected]>
Auto-Submit: Xiaocheng Hu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1131479}
aarongable pushed a commit to chromium/chromium that referenced this pull request Apr 17, 2023
This patch also adds WPTs for the anchor attribute (without popovers)
to support the HTML PR whatwg/html#9144

Fixed: 1432016
Change-Id: I3e80326268008e6beaf74389bb32c01050406a81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4434155
Commit-Queue: Joey Arhar <[email protected]>
Commit-Queue: Xiaocheng Hu <[email protected]>
Reviewed-by: Joey Arhar <[email protected]>
Code-Coverage: Findit <[email protected]>
Auto-Submit: Xiaocheng Hu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1131479}
chromium-wpt-export-bot pushed a commit to web-platform-tests/wpt that referenced this pull request Apr 17, 2023
This patch also adds WPTs for the anchor attribute (without popovers)
to support the HTML PR whatwg/html#9144

Fixed: 1432016
Change-Id: I3e80326268008e6beaf74389bb32c01050406a81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4434155
Commit-Queue: Joey Arhar <[email protected]>
Commit-Queue: Xiaocheng Hu <[email protected]>
Reviewed-by: Joey Arhar <[email protected]>
Code-Coverage: Findit <[email protected]>
Auto-Submit: Xiaocheng Hu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1131479}
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this pull request Apr 19, 2023
…r attribute changes, a=testonly

Automatic update from web-platform-tests
[anchor-position] Update layout on anchor attribute changes

This patch also adds WPTs for the anchor attribute (without popovers)
to support the HTML PR whatwg/html#9144

Fixed: 1432016
Change-Id: I3e80326268008e6beaf74389bb32c01050406a81
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4434155
Commit-Queue: Joey Arhar <[email protected]>
Commit-Queue: Xiaocheng Hu <[email protected]>
Reviewed-by: Joey Arhar <[email protected]>
Code-Coverage: Findit <[email protected]>
Auto-Submit: Xiaocheng Hu <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1131479}

--

wpt-commits: db5d9506cb37895b200037877628911afd3fac14
wpt-pr: 39576
@annevk
Copy link
Member

annevk commented May 8, 2023

Before looking at this I'd like to see topic: popover The popover attribute and friends shrink a whole lot first.

@jpzwarte
Copy link

jpzwarte commented May 19, 2023

I've moved my previous comment to #9311.

@cwilso
Copy link

cwilso commented Jun 5, 2023

@annevk I'm not sure I understand why this work is blocking on popover. Although popover is one place anchor would be useful, of course, it's not the only scenario - and it seems like popover's needs are addressed here. What is the scope of your concern for what needs to be investigated before anchor work can proceed?

@nt1m
Copy link
Member

nt1m commented Jun 6, 2023

@josepharhar @tabatkins My initial thought looking at this is whether we can leverage presentation hints in some way instead of an "implicit anchor element", while still making it work conveniently for developers.

The idea behind this seems fine to me though.

@annevk
Copy link
Member

annevk commented Jun 6, 2023

@cwilso my concern is that popover landed in the standard with lots of issues that need to be addressed and it's been taking quite a long time for them to be addressed. That makes me uncomfortable about new features.

@tabatkins
Copy link
Contributor

whether we can leverage presentation hints in some way instead of an "implicit anchor element", while still making it work conveniently for developers.

I'm not sure how that would be possible. Without an implicit anchor element, you need a named anchor element, which means that, assuming we could craft an appropriate selector (not certain that's true, haven't thought about it enough) we'd have to reserve a name just for this use-case. And an element can only have one anchor name, so it would conflict with authors using an anchor name on the element for other purposes. (Even if we change to allow multiple anchor names, which there's an open issue about, we'd still conflict since CSS has never gained a way to add to a list.) So I don't think it's possible to do this, no.

Skipping past the feasibility, tho, can I ask why you want to do this? If there's a particular reason you want to lean on presentational hints instead, I'd like to know in case it impacts other things architecturally.

@josepharhar
Copy link
Contributor Author

We want to ship this soon in chrome along with CSS anchor positioning so they can be used together.
I will continue to work on the remaining popover issues, but any feedback on this attribute in the meantime would be greatly appreciated so we have time to make changes if needed.

source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
source Outdated Show resolved Hide resolved
domenic added a commit that referenced this pull request Jul 4, 2023
Fix the backlinks to the attribute definitions, which has the effect of causing the attribute definitions to show up in the input and button element definitions. (The newlines here are, unfortunately, important.)

Also make popovertarget use the same "ID*" value space as other ID-accepting elements, as noted in #9144 (comment).
@annevk
Copy link
Member

annevk commented Jun 10, 2024

It seems we could accomplish the implicit anchor aspect of #9144 (comment) without a new attribute. By exposing the relationship between the activating element and the popover to CSS. I suspect we also have to expose that to AT and w3c/html-aam#481 seems to back that up. (Which by the way is a problem we need to avoid going forward. We should not land new markup features without the a11y side being ready.)

Yes, this one also affects layout, but that's not all that it does.

Can you clarify what it does when we leave layout out of it?

@josepharhar
Copy link
Contributor Author

Just to summarize, here are the non-presentational rationales for this attribute:

  1. Semantically "nest" two popovers, such that they are anchor positioned to each other and one doesn't close the other.
  2. A solution to allow anchor positioning to cross shadow root boundaries.

Can you clarify what it does when we leave layout out of it?

Mason's two points about anchoring across shadow boundaries and changing the topmost popover ancestor algorithm leave layout out of it, right?

It seems we could accomplish the implicit anchor aspect of #9144 (comment) without a new attribute. By exposing the relationship between the activating element and the popover to CSS.

If we can't have the anchor attribute, then I suppose it would be nice to automatically anchor position popovers to their invoker buttons but I wonder if that would be too much of a breaking change now that we have interop with popovers.

I suspect we also have to expose that to AT and w3c/html-aam#481 seems to back that up.

Should anchor positioning make AT changes when only used in CSS without the anchor attribute? If not I imagine this attribute would be great for that.

@mfreed7
Copy link
Contributor

mfreed7 commented Jun 11, 2024

The HTML attribute for anchor positioning was just discussed again at the CSSWG F2F:

w3c/csswg-drafts#9356 (comment)

The desire for this attribute was re-iterated in that conversation. Also, another (non-layout) reason for the attribute was found: it could be used to fix up sequential focus navigation order in the case that an anchored element wants to come after (or before) the anchor element in focus order. Similar to how Popover works, but for the case where popovers aren't desired.

@fantasai
Copy link
Contributor

fantasai commented Jun 25, 2024

Mason's two points about anchoring across shadow boundaries and changing the topmost popover ancestor algorithm leave layout out of it, right?

Both of those points are presentational. They're all about how anchor positioning hooks up two elements together for layout, and not anything about what it means otherwise.

I'm not saying that we don't need markup to represent anchoring. But that markup needs to be about the semantics of anchoring, not about its layout. So consider these cases:

  • An anchored element is semantically and presentationally attached to its anchor: e.g. a popup.
  • An anchored element is presentationally but not semantically attached to its anchor: e.g. a "NEW!" banner for a shopping item which is presented attached to the photo, but is not about the photo and therefore should not be semantically anchored to it (but should rather stay where it is in the DOM for accessibility purposes etc.).
  • An anchored element that is semantically attached to its anchor, but presentationally not attached to it, e.g. a popup that is laid out in the viewport or attached to an ancestor of the anchor element, but not visually related to the anchor element.

The first two use CSS anchor positioning. The first and last (but not the middle) need HTML anchoring of some kind.

This proposal doesn't address HTML's need for anchoring. It's only about presentation. To answer HTML's needs for anchoring it needs to address:

  • What are the accessibility (ARIA) bindings that anchoring should invoke?
  • How does it affect focus and reading order?
  • Does it give enough control to the author over that? E.g. maybe we need control about whether the anchored element is anchored before or after the anchor element.
  • Is it convenient enough for authors to use that they will reach for it instead of position-anchor for the cases where they should be using it instead of position-anchor?
  • Is it clear enough what it's appropriate for that we can teach authors can use it correctly?

@emilio
Copy link
Contributor

emilio commented Jun 25, 2024

The fact that CSS would override this means that we should either look at CSS for the aria semantics, or make the priority the other way around instead, somehow?

@fantasai
Copy link
Contributor

fantasai commented Jun 25, 2024

@emilio Mmm, no, like I said in #9144 (comment), there are cases where the CSS and HTML anchoring should match, and cases where it shouldn't. So CSS shouldn't override, it should just take the HTML anchoring relationship in as a default. We just need to make sure that for cases where authors should provide those semantics in HTML rather than CSS, that they're able to do so conveniently enough that they will actually do it in the HTML.

@fantasai
Copy link
Contributor

Rough cut of the minutes (Dael will post the final version) at https://www.w3.org/2024/06/27-css-minutes.html#t02
Summary:

  • RESOLVED: popovertarget creates an implicit anchor element reference
  • RESOLVED: Develop HTML markup to represent semantic anchoring relationships (and which also set the implicit anchor element) to solve non-popover use cases.
  • RESOLVED: it would be a good idea to add an imperative way to set invoker relationships between popovers.

@Howard13Kam

This comment was marked as spam.

@Jxck
Copy link

Jxck commented Aug 27, 2024

Hi Team

What is the current status of this feature ?
Any updates for discussion or implementation ?
I'd love to have this feature so I wanna catching up.

Thanks

@mfreed7
Copy link
Contributor

mfreed7 commented Sep 9, 2024

Rough cut of the minutes (Dael will post the final version) at https://www.w3.org/2024/06/27-css-minutes.html#t02 Summary:

  • RESOLVED: popovertarget creates an implicit anchor element reference
  • RESOLVED: it would be a good idea to add an imperative way to set invoker relationships between popovers.

We will get a spec PR put together for these two, soon. I've gotten started on prototyping these in Chrome.

  • RESOLVED: Develop HTML markup to represent semantic anchoring relationships (and which also set the implicit anchor element) to solve non-popover use cases.

This one comes back to your comment from above:

I'm not saying that we don't need markup to represent anchoring. But that markup needs to be about the semantics of anchoring, not about its layout. So consider these cases:

  • An anchored element is semantically and presentationally attached to its anchor: e.g. a popup.
  • An anchored element is presentationally but not semantically attached to its anchor: e.g. a "NEW!" banner for a shopping item which is presented attached to the photo, but is not about the photo and therefore should not be semantically anchored to it (but should rather stay where it is in the DOM for accessibility purposes etc.).

Isn’t this use case also semantic? I.e. “New!” is semantically connected to the shopping item. It describes the item as being “new”. Right?

  • An anchored element that is semantically attached to its anchor, but presentationally not attached to it, e.g. a popup that is laid out in the viewport or attached to an ancestor of the anchor element, but not visually related to the anchor element.

Can you give an example of this case? I’m having a hard time visualizing an example.

The first two use CSS anchor positioning. The first and last (but not the middle) need HTML anchoring of some kind.

This proposal doesn't address HTML's need for anchoring. It's only about presentation. To answer HTML's needs for anchoring it needs to address:

  • What are the accessibility (ARIA) bindings that anchoring should invoke?

@scottaohara or @aleventhal, any thoughts on this question?

  • Does it give enough control to the author over that? E.g. maybe we need control about whether the anchored element is anchored before or after the anchor element.

To clarify, “before” or “after” mean just semantically (and perhaps focus order), but not presentationally, right? I.e. anchor positioning handles where it physically goes, e.g. via position-area. Just confirming.

Separate from that, can you please give an example of an anchored element that should come semantically before its anchor? All of the examples I can think of seem semantically “after”.

  • How does it affect focus and reading order?

For anchored elements that come “after” their anchor element, it would seem that they should be immediately next in focus and reading order, akin to how popover invokers act as focus navigation scope owners. This relationship would be a bit more difficult to implement, given that the relationship goes the other way (attribute pointing from anchored element to anchor element), but it seems solvable. It also raises questions in the case that there are multiple elements all anchored to a single anchor. Likely those could be resolved also.

One difficulty that I don’t know how to solve is the “before” case. The focus navigation scope owner concept is what popovers currently use to make the popover come “just after” its triggering element, and that works well. But I’m not sure how to do the reverse - have the anchored element come just before. The natural way would be for the anchored element to be a scope owner, which owns the anchor element. But that actually means the anchor element moves in the focus order, to come just after the anchored element. They’re in the right order relative to each other, but likely not in the right order relative to the rest of the document. Additionally, the case where there are multiple anchored elements gets really tricky - I think only one of them can own the anchor element. Any ideas for how to spec/implement this? This is why I asked above about actual use cases for "before" - it might help us understand how it should work.

  • Is it convenient enough for authors to use that they will reach for it instead of position-anchor for the cases where they should be using it instead of position-anchor?

This is a good question: I think as long as it’s as simple as an idref, the answer is likely “yes”. I’ve already tried to reach for this concept in internal implementations of elements such as <video>.

  • Is it clear enough what it's appropriate for that we can teach authors can use it correctly?

Good question. I think the answer should be “yes”, but I think that depends on the complexity of the feature. If it’s just anchor=idref then this seems like a simple concept to explain. If it gets more complicated, then maybe not.

@aleventhal
Copy link

Hi @fantasai, thanks for raising important a11y questions. Here are some thoughts, after talking this over with Scott O’Hara and Jocelyn Tran.

What are the accessibility (ARIA) bindings that anchoring should invoke?

It seems right to support a11y for the anchor attribute in a similar way as discussed in HTML-AAM GitHub issue w3c/html-aam#545.

There is an aria-details relation set between the anchor and the anchored object. This allows screen reader users to be notified when there is something anchored to another element that they have navigated to, and navigate to the anchored object and then back. Authors also have the option of overriding this behavior, e.g. using ARIA to set a different relationship, in which case the automatic details will not be set. The consensus in the HTML-AAM issue for CSS anchors was that setting the relationship by default will do more good than harm in cases where there wasn't a semantic relationship.

How does it affect focus and reading order?

Reading order:
We don't need to affect reading order for assistive technologies because of the details relationship. By using the details relation, we are treating the anchor itself as the primary object, and the anchored object is supplemental, such that the user can branch off to it and come back. If the author wants the actual reading order to change, they can use aria-owns to point from the anchor to the anchored element,

Focus order:

  • The focus order might be unwanted in some cases. Do we think this is the rarer situation?
  • The author can still control either of these directly by putting the anchored object next in the DOM (and if they do so, the automatic aria-details relation will not be set).
  • If the author wants to also affect focus order, then the anchored content could be a popover (auto or manual), which will handle focus order..
  • There is not another great way to only affect focus order (tabindex is clearly bad),
  • We could see a use case for an attribute that does for focus order what popovertarget does, e.g. focusdetour=[id] or focusbranch=[id]. Perhaps focusbranch=”” would turn off focus branching for something like popovertarget than has it automatically.
  • We might be convinced that the default behavior for the anchor attribute should include focus branching by default, but need to hear more arguments supporting that.

@chrisdholt
Copy link

chrisdholt commented Sep 24, 2024

Forgive a potentially dumb question, but we've had problems leveraging the current anchor positioning API with custom elements. Is it reasonable to assume that the anchor attribute would work with Web Components as though they were native elements? To be specific - there is no element within the shadow root where reference target would be necessary, the element itself is the target.

@mfreed7
Copy link
Contributor

mfreed7 commented Sep 26, 2024

Forgive a potentially dumb question, but we've had problems leveraging the current anchor positioning API with custom elements. Is it reasonable to assume that the anchor attribute would work with Web Components as though they were native elements? To be specific - there is no element within the shadow root where reference target would be necessary, the element itself is the target.

Anchor positioning should "work" on custom elements in the same way as regular elements. If you've found something that isn't working on the Blink implementation, perhaps file a bug?

@chrisdholt
Copy link

Forgive a potentially dumb question, but we've had problems leveraging the current anchor positioning API with custom elements. Is it reasonable to assume that the anchor attribute would work with Web Components as though they were native elements? To be specific - there is no element within the shadow root where reference target would be necessary, the element itself is the target.

Anchor positioning should "work" on custom elements in the same way as regular elements. If you've found something that isn't working on the Blink implementation, perhaps file a bug?

Can do - essentially, we're finding (unless it's user error) that we can't use anchor() without creating a constructable stylesheet in the light DOM; the adopted stylesheet is adopted to the shadow root which is our current hypothesis. I'll have someone open a bug. Thanks @mfreed7.

As far as the question above, I just want to elevate the edge case where Reference Target isn't applicable.

@davatron5000
Copy link

Looped in by @chrisdholt, I was working on an anchored tooltip this week and have a reduced example.

Given the DOM structure ....

<button id="anchor" popovertarget="tooltip">Text</button>
<tool-tip id="tooltip" popover>Content</tool-tip>

The following CSS works in Light DOM...

<style>
  #anchor { anchor-name: --my-name; }
  #tool-tip { 
    position-anchor: --my-name; 
    bottom: anchor(--my-name, top); 
  }
</style>

But moving that into the Shadow DOM doesn't work.

<style>
  #anchor { anchor-name: --my-name; }
</style>
<button id="anchor" popovertarget="tooltip">Text</button>
<tool-tip id="tooltip" popover>
  <template shadowrootmode="open">
    <style>
      :host { 
        position-anchor: --my-name; 
        bottom: anchor(--my-name, top); 
      }
    </style>
    <slot></slot>
  </template>
  Content
</tool-tip>

The "CSS ref" to --my-name is lost when traversing the shadow boundary. That means anchor(--my-name ...), etc won't work in the Shadow styles either. And (just in case someone is curious) assigning --anchor: --my-name to a CSS Custom Property doesn't work either.

An anchor attribute would be awesome, but ideally accessible/referenceable from the ShadowRoot :host as well as shadow children.

@mfreed7
Copy link
Contributor

mfreed7 commented Sep 27, 2024

The following CSS works in Light DOM...
But moving that into the Shadow DOM doesn't work.

The "CSS ref" to --my-name is lost when traversing the shadow boundary. That means anchor(--my-name ...), etc won't work in the Shadow styles either. And (just in case someone is curious) assigning --anchor: --my-name to a CSS Custom Property doesn't work either.

Ahh - thanks for the clarification. Note that finding an anchor says:

...
el’s anchor name and anchor spec are both associated with the same tree root.

and also this:

Note: An anchor-name defined by styles in one shadow tree won’t be seen by anchor functions in styles in a different shadow tree, preserving encapsulation. However, elements in different shadow trees can still anchor to each other, so long as both the anchor-name and anchor function come from styles in the same tree, such as by using ::part() to style an element inside a shadow. (Implicit anchor elements also aren’t intrinsically limited to a single tree, but the details of that will depend on the API assigning them.)

So in your example, you'd have to position the tooltip using your first ("working") CSS, where you are anchoring in the light DOM, and not the one where you set position-anchor on :host from inside the shadow root, because in that case you're trying to cross shadow root bounds with the anchor reference.

Also note that last sentence, which alludes strongly to this issue about the anchor attribute.

mfreed7 added a commit to mfreed7/html that referenced this pull request Oct 28, 2024
This includes two related changes:
 1. The `showPopover()` and `togglePopover()` methods now include an
    options bag that allows setting the popover invoker.
 2. Popover invokers (declaratively or imperatively set) now create
    an implicit anchor reference for that popover.

This new behavior was resolved in the [WHATWG/CSSWG/OpenUI joint task
force meeting on June 26, 2024](whatwg#9144 (comment)).

Closes whatwg#10442
Closes whatwg#10675
domenic pushed a commit to mfreed7/html that referenced this pull request Nov 15, 2024
This includes two related changes:
 1. The `showPopover()` and `togglePopover()` methods now include an
    options bag that allows setting the popover invoker.
 2. Popover invokers (declaratively or imperatively set) now create
    an implicit anchor reference for that popover.

This new behavior was resolved in the [WHATWG/CSSWG/OpenUI joint task
force meeting on June 26, 2024](whatwg#9144 (comment)).

Closes whatwg#10442
Closes whatwg#10675
domenic pushed a commit that referenced this pull request Nov 15, 2024
This includes two related changes:

1. The showPopover() and togglePopover() methods now include an options bag that allows setting the popover source.

2. Popover sources (declaratively or imperatively set) now create an implicit anchor reference for that popover.

See discussion in #9144 (comment). Closes #10442. Closes #10675.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.