accname icon indicating copy to clipboard operation
accname copied to clipboard

[accname] The spec as written for computing accessible names doesn’t result in traversing into hidden subtrees to find “un-hidden” child nodes

Open sideshowbarker opened this issue 1 year ago • 4 comments

Given the following test case:

<h2
  class="ex"
  data-testname="heading with name from content, containing element that is visibility:hidden with nested content that is visibility:visible"
  data-expectedlabel="visible to all users, un-hidden for all users"
>
  visible to all users,
  <span style="visibility: hidden;">
    hidden from all users,
    <span id=bar style="visibility: visible;">un-hidden for all users</span>
  </span>
</h2>

That case says the expected accessible name for that h2 element is visible to all users, un-hidden for all users — that is, the text content of the first text node, but also the text content of that “un-hidden” span that’s nested inside a hidden span.

Now, looking at the spec steps at https://w3c.github.io/accname/#computation-steps, the first step in the algorithm after the “initialization” step is this:

A. Hidden Not Referenced: If the current node is hidden and is:

i. Not part of an aria-labelledby or aria-describedby traversal, where the node directly referenced by that relation was hidden. ii. Nor part of a native host language text alternative element (e.g. label in HTML) or attribute traversal, where the root of that traversal was hidden.

Return the empty string.

So, when my code hits that <span style="visibility: hidden;"> element, it finds that:

  1. It’s a hidden node
  2. It’s not part of an aria-labelledby or aria-describedby traversal
  3. Nor part of a native host language text alternative element

And therefore, I return the empty string for it, and stop there.

More specifically, I don’t descend any further into the subtree for that <span style="visibility: hidden;"> element — because the spec doesn’t tell me to do that. Instead the spec just says, “Return the empty string”. And there’s nothing else in the algorithm that tells me to do anything with the child nodes of that un-referenced <span style="visibility: hidden;"> element.

In other words, there’s no way per-spec that I can ever get to that <span id=bar style="visibility: visible;"> “un-hidden” child node, in order to evaluate if it’s “un-hidden”.

Link to the version of the specification or documentation you were looking at at.

https://w3c.github.io/accname/#computation-steps

Does the issue exists in the editors draft (the editors draft is the most recent draft of the specification)? Yes.

sideshowbarker avatar Nov 27 '24 13:11 sideshowbarker

I didn't think that child elements of visibly hidden nodes were traversed if not explicitly referenced via IDREF.

But, then I thought this might be another thing defined already in html-aam, but after reading through https://w3c.github.io/html-aam/#accname-computation I don't see anything specific about heading elements (@scottaohara please keep me honest if I just missed it)

I'm not sure if this would be a gap in html-aam spec since it's related to a html element, or if it should be in this spec. Either way it seems as though some amount of clarification should be provided somewhere.

MelSumner avatar Mar 18 '25 20:03 MelSumner

this is some nuance i don't think any spec adequately covers.

the intent here is that while a node may be marked as visibility: hidden and thus that node is ignored in the a11y tree - since child nodes could be unhidden, those nodes do exist in the a11y tree and thus should still be used for naming (per the wpt / chrome/firefox/safari browsers presently do this)

the first point in the note that follows this section should probably be updated (or maybe separated into two points) to clarify that visiblity: hidden content may not be entirely hidden if child nodes are re-exposed with visibility: visible. in those cases, browsers shouldn't only ignore the parts that are hidden - and continue to traverse the content that is exposed to the a11y tree.

scottaohara avatar Mar 25 '25 15:03 scottaohara

the intent here is that while a node may be marked as visibility: hidden and thus that node is ignored in the a11y tree - since child nodes could be unhidden, those nodes do exist in the a11y tree and thus should still be used for naming (per the wpt / chrome/firefox/safari browsers presently do this)

Ladybird does use the un-hidden descendant DOM nodes as well. We’re passing the same WPT tests.

But we’re not passing the WPT tests because we conform to the actual spec requirements as currently written. Instead we’re passing the WPT tests because we’re ignoring what the spec requires and instead traversing into the subtree. And I’d imagine that other engines must be doing something similar.

Regardless, it doesn’t seem to me that the WPT tests conform to the spec requirements. I don’t see how they possibly could — for the reason outlined in description for this issue.

So the fact that implementations are passing the WPT tests is not on its own evidence that the spec is correct. It’s necessary to also confirm that the implementations have actually strictly implemented the spec requirements as written.

the first point in the note that follows this section should probably be updated (or maybe separated into two points) to clarify that visiblity: hidden content may not be entirely hidden if child nodes are re-exposed with visibility: visible. in those cases, browsers shouldn't only ignore the parts that are hidden - and continue to traverse the content that is exposed to the a11y tree.

But browsers operate on DOM nodes in the document in tree order to build the accessibility tree, right? And the accname refers to operating on DOM nodes — including the steps in https://w3c.github.io/accname/#computation-steps.

Are you saying that instead what’s intended is that browsers are meant to perform the steps in https://w3c.github.io/accname/#computation-steps by operating on the built accessibility tree?

If not, if the requirements in those steps are in fact for browsers to operate on DOM nodes, then I don’t see how — without traversing into the entire subtree for a visiblity: hidden DOM node — browsers are expected to determine that the DOM node contains descendant DOM nodes re-exposed with visibility: visible, and only then continue to traverse the content.

sideshowbarker avatar Mar 26 '25 03:03 sideshowbarker

Are you saying that instead what’s intended is that browsers are meant to perform the steps in https://w3c.github.io/accname/#computation-steps by operating on the built accessibility tree?

I say this in all sincerity and not as a browser implementor - but i have been working under the rational that that's exactly what browsers should be doing - using the accessibility tree. Otherwise, i'm a bit perplexed as to how to account for the following example where the name of the button is/should be "foo" due to the div and its text content being communicated as a child of the button in the a11y tree - but obvs not in the DOM / as well as the use case already outlined here concerning CSS visibility:

<button aria-owns=f></button>
...
<div id=f>foo</button>

<!-- or -->
<button aria-owns=f1></button>

<div aria-hidden=true>
	<div id=f1>foo</div>
</div>

similarly, i would not expect these calculations to only be operating on DOM nodes since the spec also calls out / account for CSS pseudo elements as participating in computing accNames.

If i'm somehow completely off base here, i'd love to be corrected.

scottaohara avatar Mar 26 '25 20:03 scottaohara