Repository navigation
Clarify relationship between aria-hidden and aria-owns - #1839
Conversation
|
Two points to mention: I'm encountering a problem similar to #1818 but the other way around, and I'm not sure this PR fully handles it 🤔 The case in #1818 was: <ul aria-owns="li"></ul>
<div aria-hidden="true">
<li id="li">Child node</li>
</div>That is, a not-hidden element What happens in the reverse case: <div aria-hidden="true">
<div id="owner" aria-owns="li" />
</div>
<ul> <li id="li">Item</li> </ul>In that case, a hidden element Second point is that the language in §7.1 Excluding Elements from the Accessibility Tree uses a lot of "descendant" and other tree-related wording, notably for the case concerning this PR:
Should there be a precision that "descendants" here mean "either descendant in the DOM tree, or descendant in the accessibility tree where |
|
For the second point: #1150 |
Mmm, thanks for poking at this, @Jym77. I hadn’t considered that reverse case. “Owning element” is currently defined as “any DOM ancestor of the element, or any element with an In this reverse scenario, |
|
@adampage That actually makes sense 😄 <div aria-hidden="true" aria-owns="li"></div>
<ul> <li id="li">Item</li> </ul>In that case, the current behaviour is to expose I guess it's a bit of a question which of Can get weirder with a case like: <div aria-hidden="true" aria-owns="foo"></div>
<div id="foo" aria-owns="bar"></div>
<div id="bar"></div>Now, |
|
This discussion has been super helpful, @Jym77, thank you. 😁 I think you hit the nail on the head with the question of which attribute “acts faster”. Let’s say that this PR now includes some additional text (somewhere appropriate in the spec) to the effect of: “Changes to ownership are resolved in DOM order. If both Now let’s apply that to the four scenarios that have come up. In the initial #1818 example: <ul aria-owns="li"></ul>
<div aria-hidden="true">
<li id="li">Child node</li>
</div>...the In the reverse case: <div aria-hidden="true">
<div id="owner" aria-owns="li" />
</div>
<ul> <li id="li">Item</li> </ul>... In the follow-up simplified case: <div aria-hidden="true" aria-owns="li"></div>
<ul> <li id="li">Item</li> </ul>... In the follow-up weirder case: <div aria-hidden="true" aria-owns="foo"></div>
<div id="foo" aria-owns="bar"></div>
<div id="bar"></div>...the previous story is essentially true again. The original intention of this spec clarification was to align with the current Chrome & Firefox behavior, so I built out all four of these scenarios in Codepen and tested them with macOS + VoiceOver + Chrome. Each outcome I described above is correctly demonstrated by that AT combo. Whew. Having said all that, would you agree that the gist of my additional spec proposal is helpful & accurate? And that it would reasonably lead to the interpretations I described for each of those four scenarios? Are there yet other ambiguous scenarios lurking out there? 😅 Thanks again! |
Yes, I think that clarification works. Maybe we need to add that change of ownership is only initiated by non-hidden node (that's more or less the second sentence but making it clear that one should stop looking for This also makes it clear that Great clarification 👍 |
|
was following along with this until:
this statement has made me wonder if this actually makes sense or not. since display none does modify the a11y tree... and then i'm not sure what case 2 refers to? the second of Adam's examples in his last comment, or the second odd case you brought up, @Jym77 ? |
|
Yep, poor writing on my side 🙈 and messing up things badly… <ul aria-owns="li"></ul>
<div style="display: none">
<li id="li">Child node</li>
</div>case 1 not 2 in Adam's list with This does not expose That is of course linked to non-interference with the host language ( |
|
Thanks for the correction/clarification. Yah that makes sense again now. |
3ddc773 to
4d5c3a6
Compare
This reverts commit a3dc2a9.
|
So, I reacquainted myself with the spec’s definition of “hidden”:
Based on that, I took another pass at the Beyond that, I wordsmithed the clarifications we discussed earlier in this thread and added them to the |
|
I feel there is still a small clarification needed to say that Owning element states:
Because of the "or", and no mention of unicity, in case 1 above <ul aria-owns="li"></ul>
<div aria-hidden="true">
<li id="li">Child node</li>
</div>Both the So, without disambiguating that, the Should we change the definition of "owning element" to state something like
Otherwise, I think this is correct and expresses what is needed 👍 |
|
I just want to note that @Jym77's recommended definition of owned is nice, and, that there is also a 1.3-blocking issue related to inconsistent use the term "owned by", just like how hidden was just revisited: The "owned by inconsistencies" can be addressed before of after this PR, but it might also lead to a term change or term update. |
|
Thanks very much, @scottaohara! I committed your example and then made a couple follow-on editorial tweaks. Does this read okay to you?:
|
|
i'm going to approve as is - but i don't think "also" needed to be added. that made me initially think that the sentence was trying to say that the element that was attempting to be reparented was hidden from the a11y tree - and it made me go back to look if that had been changed |
|
Updated. Thank you, @scottaohara. 🙏🏻 |
|
Tentatively labeling this "waiting for implementations" since the thread on WPT leaves me wondering if implementation work is needed after all. Please correct me if I'm getting it wrong (e.g., merge the PR). |
|
Agenda-ing this also for the tests. We should get this landed, and the tests, if we want to move forward with this change. |
|
Here are the latest browser results for the companion WPT test. |
|
Just read the minutes from yesterday's meeting: https://www.w3.org/2025/09/04-aria-minutes.html#9476 Since this is largely in agreement with two implementations (besides minor bugs) I think we should land this change THEN open a bug on webkit and everyone else. |
|
Actually, I said this is ready for merge, but it would be nice to get an approving review from @cookiecrook first |
cookiecrook
left a comment
There was a problem hiding this comment.
Approving with one editorial clarification.
Co-authored-by: James Craig <cookiecrook@users.noreply.github.com>
|
Thanks, @cookiecrook. I’ve committed that suggestion and merged in the latest, @spectranaut 🚀 |
SHA: 31766e3 Reason: push, by spectranaut Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Per the ARIA spec, "User agents MUST NOT resolve aria-owns when it is set on an element that has been excluded from the accessibility tree" [1]. AXRelationCache::IsValidOwner() already rejected aria-hidden owners, but not owners that are display:none (e.g. via the hidden attribute), visibility:hidden, or inside such an ancestor. As a result, a hidden element could pull a visible element out of its natural parent and park it under an invisible, ignored subtree, which among other things emptied the natural parent's name-from-contents. This made Chromium fail two subtests of external/wpt/accname/aria-owns.html that Firefox and Safari pass: * Ignore aria-owns when on an element that is hidden from all users * Computed name of parent heading persists when aria-owns fails to relocate its contents Note that this deliberately reverses behavior introduced in https://crrev.com/c/2575445 (crbug.com/1155617), which ensured that invisible aria-owns sources are included in the tree so that they could own visible children. That predates the spec text above (added in w3c/aria#1839). Elements with aria-owns are still force-included in the tree so that their relation bookkeeping can be set up and torn down; they just no longer get to own anything while hidden. This CL: - Rejects owners for which IsHiddenViaStyle() is true, alongside the existing IsAriaHidden() check. Owned children were already required to have a layout object, so this only closes the gap on the owner side. - Re-validates aria-owns when the visibility of an element with aria-owns changes. Unlike display:none and aria-hidden changes, a visibility change does not rebuild the AXObject (which would re-queue the owner), so without this an owner that became visible again would never re-establish its relation. Dropping the relation when the owner becomes hidden already happens via ValidatedAriaOwner() when the owner's children are rebuilt. - Rebaselines aria-owns-from-display-none, which encoded the old behavior, and adds aria-owns-from-hidden-owner (static scenarios) and accessibility/aria-owns-hidden-owner.html (static + dynamic scenarios, including hidden/visibility round trips). - Removes the WPT expectation file for accname/aria-owns.html, which now passes entirely. Related: crbug.com/409069366 (re-queue aria-owns when an AXObject is recreated) is why the display:none round trip already worked and only the visibility round trip needed the new hook. crbug.com/503872382 (ValidatedAriaOwner() restores the natural parent when an owner becomes invalid) is the cleanup path this change relies on when an owner is hidden. Known limitation: the AX cache only learns about visibility changes via LayoutObject::StyleDidChange(), so an owner that is display:contents is not re-validated when its visibility is toggled at runtime. Static display:contents owners (visible or hidden) are handled correctly. This is a pre-existing gap in the style-change plumbing; a complete fix would need a notification from Element::RecalcOwnStyle(). Not addressed here since the combination is rare and nothing gets worse than before. Out of scope: spec rule 2 also says that a visibility:hidden *target* must not be owned; Chromium currently keeps such a target owned but ignored. The WPT does not test this; left for a follow-up. [1] https://w3c.github.io/aria/#aria-owns The new dump test is not registered in the Android WebContentsAccessibilityTreeTest, as its Android expectations cannot be generated without an Android build; happy to add them if a reviewer can supply the output. R=aleventhal@chromium.org, dtseng@chromium.org ARIA spec and Firefox/Safari. The referenced elements stay with their natural parent. AX-Relnotes: aria-owns is now ignored on elements that are hidden via display: none, the hidden attribute, or visibility:hidden, matching the Bug: 574690367 Change-Id: I6854152ae48fe67a0099ab15ce46ec1f3b9e2707 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8603287 Commit-Queue: Sarah Drasner <sdrasner@google.com> Reviewed-by: David Tseng <dtseng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1724275}
Closes #1818.
The definition of Owning Element is already inclusive of both DOM ancestry and ownership via
aria-owns:Because of this, I’m thinking it’ll be sufficient to swap out “ancestors” for “owning elements” in
aria-hidden’s description.I also editorially removed what I believe is an unhelpful comma.
Test, Documentation and Implementation tracking
Once this PR has been reviewed and has consensus from the working group, tests should be written and issues should be opened on browsers. Add N/A and check when not applicable.
aria-ownsand hiding techniques in assorted scenarios web-platform-tests/wpt#44822Preview | Diff