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

WebKit does not fall back to 'nameFrom: contents' on aria-describedby reference when referenced element contains role="status" thus not announcing content via VoiceOver #2381

Open
gjellin opened this issue Nov 20, 2024 · 14 comments
Assignees

Comments

@gjellin
Copy link

gjellin commented Nov 20, 2024

Description of bug or feature request

Nothing is announced when focus is placed on an input with an aria-describedby reference and the referenced node contains role=status, role=alert or aria-live. Occurs on Safari and Firefox, but works on Chrome.

Example:

<input maxlength="255" name="Name" required="" type="text" aria-describedby="help-message-1503">

<div id="help-message-1503" role="status">Complete this field.</div>

In the following codepen, the first example has the role=status and the second one does not. Only the second one announces the referenced content: https://codepen.io/A11yGreg/pen/dyxazYY

I submitted a bug to WebKit and Tyler Wilcock advised me to submit a bug here. He believes the issue is caused by the following:

When WebKit needs to resolve the text behind aria-describedby, it combines the "accessible names" for each element-by-id pointed to in the aria-describedby. WebKit computes the accessible name for an element by either using the nameFrom: author algorithm, or the nameFrom: contents algorithm (https://w3c.github.io/aria/#namecalculation), or computes no name for the role (see "prohibited" in the spec link). Because role="status" is nameFrom: author, that means we do not consider descendants when computing the name, only author-provided markup on the role="status" element like aria-label.

I don't know why this works in Chrome. It's possible they've noticed how this behavior can be unintuitive, and workaround the spec to provide a better user experience. But probably the best solution is for an issue to be filed on the WAI-ARIA spec so all browsers can become aligned.

Will this require a change to CORE-AAM?

Will this require a change to the ARIA authoring guide?

@scottaohara
Copy link
Member

I've noticed this before as well, it's definitely caused frustration to developers. But this is not unique to aria-describedby, as we've similarly talked about this in the context of trying to name elements as well.

see: https://codepen.io/scottohara/pen/YzmoxXJ

@twilco
Copy link
Contributor

twilco commented Nov 20, 2024

For roles that are nameFrom: author, Chrome will prefer to expose that. But if there is no nameFrom: author for the element, Chrome falls back to exposing nameFrom: contents, while WebKit and Gecko don't. This behavior seems reasonable to me — I wonder if it should be specified (is it already?), and / or codified in an accname WPT.

@twilco
Copy link
Contributor

twilco commented Nov 20, 2024

And for what it's worth, WebKit and Gecko match Chrome's behavior in this testcase if aria-describedby is swapped with aria-labelledby, i.e.:

<input type="text" aria-describedby="message">
<div id="message" role="status">Complete this field</div>

All three engines fallback to exposing nameFrom:contents (which is "Complete this field") because the role="status" doesn't have a nameFrom: author. So really, Chrome is consistent in how it computes aria-describedby and aria-labelledby, while WebKit and Gecko aren't (at least in testing these basic examples).

@cookiecrook
Copy link
Contributor

Thanks for the thorough diagnosis @twilco!

@spectranaut
Copy link
Contributor

Discussed in today's working group meeting: https://www.w3.org/2024/11/21-aria-minutes#bae2

@JAWS-test
Copy link
Contributor

I think it's a big misunderstanding on the part of browsers that they don't transmit the text content as a description for role=status, for example, if it is referred to via aria-describedby. A div element, for example, may not be labelled at all (https://www.w3.org/TR/wai-aria-1.3/#generic) - consequently, according to this logic, I should never refer to a div via aria-labelledby or aria-describedby.

The ‘Name From’ specification in the ARIA specification, however, means something different: If I am at the element (i.e. do not refer to the element via aria-labelledby or aria-describedby), then a div, for example, cannot be labelled (but still has its text content), whereas a role=status can be labelled and has its text content. A screen reader should first output the labelling of the live region for role=status and then the text content.

Unfortunately, this is not formulated clearly enough in AccName, which leads to absurd misunderstandings. This must be fixed!

@JAWS-test
Copy link
Contributor

JAWS-test commented Nov 22, 2024

Related: w3c/accname#153 (comment) and w3c/accname#120. The problem has been known for several years and unfortunately nothing has been done so far. I would very much welcome it if this could finally change!

@jnurthen
Copy link
Member

jnurthen commented Dec 5, 2024

@jcsteh & @cookiecrook what is your opinion on making a change here to align with chrome?

@spectranaut
Copy link
Contributor

discussed in today's meeting: https://www.w3.org/2024/12/05-aria-minutes#8798

@spectranaut spectranaut removed the Agenda label Dec 5, 2024
@jcsteh
Copy link

jcsteh commented Dec 6, 2024

This comes back to the question of when elements should be traversed for name computation even when they only permit name from author. An attempt was made to address this in #1821 (comment), but that seems to have stalled.

As I explained in that comment, my concern with Chromium's behaviour (falling back to name from contents regardless of role) is that you could end up with extremely long names/descriptions. It also makes the behaviour inconsistent between aria-labelledby/describedby vs name from contents traversals.

The more restrictive fix here would be to treat role status as name from author + always traverse (using the terminology from the issue linked above). I think that's reasonable in this case, given that status is not likely to be as big as, say, a massive table.

@jcsteh
Copy link

jcsteh commented Dec 6, 2024

And for what it's worth, WebKit and Gecko match Chrome's behavior in this testcase if aria-describedby is swapped with aria-labelledby

I can't reproduce this. Gecko is consistent with aria-labelledby and aria-describedby here: no label, no description. I agree that isn't intuitive, but it is currently consistent.

@gjellin
Copy link
Author

gjellin commented Dec 6, 2024

Note; I do believe that Gecko does fall back with aria-describedby (same behavior as Chromium) when using role=alert, but not with role=status.

@jcsteh
Copy link

jcsteh commented Dec 6, 2024

Note; I do believe that Gecko does fall back with aria-describedby (same behavior as Chromium) when using role=alert, but not with role=status.

That's correct. Gecko treates role alert as name from author + always traverse. In contrast, role status is (currently) treated as name from author + never traverse.

@accdc
Copy link
Contributor

accdc commented Dec 12, 2024

Personally I'm in favor of simplifying this, but this is just me.

If a person explicitly points to an element for a name or description using aria-labelledby or aria-describedby, I would prefer for that referenced content to be traversed as expected by the author regardless if that referenced element has a role or not, and regardless of what the role is.

The logic being, if an author has taken the effort to point at something, they probably have a good reason for doing it.

I'm not referring to child roles, but only the container that is explicitly referenced using the id of that element.

Example:

<button aria-labelledby="lbl"></button>
<div id="lbl">Label here</div>

Should do the samething as:

<button aria-labelledby="lbl"></button>
<div role="status" id="lbl">Label here</div>

However, when not explicitly referenced, I think it should fall back on the original algorithm and omit the content of certain roles if they are contained within that referenced container.

Example:

<button aria-labelledby="lbl"></button>
<div id="lbl">
Label here
<div role="status">Ignore This</div>
</div>

Perhaps the status role here is a bad example, but replace this with grid, listbox, or whatever doesn't make sense to traverse and you can see why this would be important to maintain.

Like I said though, this is just and idea.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants