aria-practices
aria-practices copied to clipboard
Explanation about aria-labelledby with hidden content not clear
Regarding: https://w3c.github.io/aria-practices/#naming_with_aria-labelledby: "It incorporates content from elements regardless of their visibility, i.e., it even includes content from elements with the HTML hidden attribute, CSS display: none, or CSS visibility: hidden in the calculated name string."
The hint for hidden labels is not quite clear, because firstly aria-hidden is not mentioned and secondly it is not explained when exactly hidden labels are output and when not (only if they are directly referenced by aria-labelledby, not if content is hidden within the element). See: https://w3c.github.io/accname/: "If the current node is hidden and is not directly referenced by aria-labelledby or aria-describedby, nor directly referenced by a native host language text alternative element (e.g. label in HTML) or attribute, return the empty string. Hidden: Indicates that the element is not visible, perceivable, or interactive to any user. An element is considered hidden if it or any one of its ancestor elements is not rendered or is explicitly hidden."
In addition, a note can be added that this unfortunately does not work reliably, see https://github.com/FreedomScientific/VFO-standards-support/issues/251
I agree that the language is not as thorough as the spec. In our attempt to keep the language as straightforward as possible, we lost the point about omission of hidden descendants of elements referenced by aria-labelledby. We should address this.
We also did not include an exhaustive list of every way to hide content.
It's not clear what the value of referencing an element that has aria-hidden="true" on it with aria-labelledby if that element is actually visible on screen. It seems like a bad pattern that should never be used. The fact that the possibility is included in the spec does not necessarily mean that we want to talk about it in this section. We avoid anti-patterns. If there is a case for documenting this as a useful feature of the way the naming algorithm works, then we could certainly add it in.
I consider aria-hidden to be very useful for labels because it prevents a label from being output multiple times when reading linearly with the screen reader:
- once at the position in the source code where the label is located
- once for the element that refers to the label via aria-labelledby.
This is particularly confusing when the label and element are located in different places in the source code. For sighted users the label is also important, therefore it should not be hidden, but only hidden with aria-hidden.
An example would be:
<label for=1>Postcode</label> / <label for=2>City</label> <input id=1><input id=2>
@JAWS-test commented:
I consider aria-hidden to be very useful for labels because it prevents a label from being output multiple times when reading linearly with the screen reader:
- once at the position in the source code where the label is located
- once for the element that refers to the label via aria-labelledby.
This is particularly confusing when the label and element are located in different places in the source code. For sighted users the label is also important, therefore it should not be hidden, but only hidden with aria-hidden.
An example would be:
<label for=1>Postcode</label> / <label for=2>City</label> <input id=1><input id=2>
Oh,no, please do not hide those with aria-hidden. Hiding the labels then forces the user to use specific keys to hear the label with some screen readers.
Consider that example with JAWS. If you use aria-hidden, then you will only hear the label if you have smart nav on, or if you tab into the field, or if you use insert+tab. But, if reading with the arrow keys, you just hear two edit fields.
Additionally, there is no way to read through the labels character by character with most screen readers if you apply aria-hidden.
Your objections are not only valid for aria-hidden, but also for hidden. So the question would be what hidden content in the label should be good for...
My example leads only with certain combinations of screenreader and browser to the output described by you. Others output the label even when reading linearly. Especially if you use aria-labelledby instead of label for.
A frequently seen example from practice are labels of grid cells that are located at the bottom of the page. Their output at the end of the page is very confusing. That's why I think it makes sense to mark them with aria-hidden.
Additionally, there is no way to read through the labels character by character with most screen readers if you apply aria-hidden.
If this is an important argument, it should generally be discouraged from hiding labels.
It is generally discouraged to hide labels.
Consider that example with JAWS. If you use aria-hidden, then you will only hear the label if you have smart nav on, or if you tab into the field, or if you use insert+tab. But, if reading with the arrow keys, you just hear two edit fields. Additionally, there is no way to read through the labels character by character with most screen readers if you apply aria-hidden.
@mcking65: None of that is true. If the hidden label is output (as tested at https://github.com/FreedomScientific/VFO-standards-support/issues/251), JAWS will output it correctly with all navigation methods (arrow keys, tab, E, F, INS+Ctrl+E, INS+F5) and it can also be read character by character. If it is not hidden, it is output multiple times. This applies to Chrome, for example. In IE 11 this doesn't work, but the hidden label is generally not output, so it's a bug of IE 11 and not a problem of the design pattern.
Tested with
<label for=1 aria-hidden=true>Postcode</label>
<label for=2 aria-hidden=true>City</label>
<input id=1>
<input id=2>
@JAWS-test commented
Your objections are not only valid for
aria-hidden, but also forhidden. So the question would be what hidden content in the label should be good for...
These are opposite situations.
Using aria-hidden="true" on visible content is the opposite of referencing content hidden with display:none with aria-labelledby.
Using aria-hidden in this way is an attempt to control screen reader verbosity by hiding content that others can see. This can be very risky. It is generally not recommended except in cases where benefit is high and where it is possible to ensure risk is non-existent.
Using aria-labelledby to reference content that is not visually displayed is providing extra information to screen reader users. This should only be done as a last resort when necessary. Always prefer visible accessible names.
A frequently seen example from practice are labels of grid cells that are located at the bottom of the page. Their output at the end of the page is very confusing. That's why I think it makes sense to mark them with aria-hidden.
While columnheaders at the bottom are rare, I am not sure why you would claim they are more confusing to screen reader users than other users. To avoid confusion, properly mark up the column headers. Please don't hide them. That will be particularly confusing to screen reader users with some vision.
@JAWS-test commented:
Additionally, there is no way to read through the labels character by character with most screen readers if you apply aria-hidden.
If this is an important argument, it should generally be discouraged from hiding labels.
It is discouraged. One of the cardinal rules of naming is to prefer visible content for accessible names.
That said, using content that is not visually displayed for an accessible name is more screen reader friendly than hiding a visible label from a screen reader with aria-hidden.
@JAWS-test commented:
@mcking65: None of that is true. If the hidden label is output (as tested at FreedomScientific/VFO-standards-support#251), JAWS will output it correctly with all navigation methods (arrow keys, tab, E, F, INS+Ctrl+E, INS+F5) and it can also be read character by character. If it is not hidden, it is output multiple times. This applies to Chrome, for example. In IE 11 this doesn't work, but the hidden label is generally not output, so it's a bug of IE 11 and not a problem of the design pattern.
Tested with
<label for=1 aria-hidden=true>Postcode</label> <label for=2 aria-hidden=true>City</label> <input id=1> <input id=2>
Not sure how you are testing this snippet of code, but your results are very different from mine. When I read through a page with this code embedded, using up/down arrow keys, the edits are completely naked. The only way to get the label is to query for it with insert+tab or insert+up. I tested in Firefox and Chrome.
Yes, the fields have accessible names. Yes, the code is valid. Yes, adding aria-hidden removes some excess verbosity in some browsers with some screen readers. But, aria-hidden also has worse negative ramifications. So, please do not use it.
Please, never, never try to fix screen reader bugs, such as excess verbosity, with extra ARIA. You'll just create other negative side effects.
It is discouraged. One of the cardinal rules of naming is to prefer visible content for accessible names.
Unfortunately I did not find this statement in the mentioned documents
Not sure how you are testing this snippet of code
With JAWS 2019.1907.42 and Chrome 76.0.3809.100. I have tested it both in this form (thanks to tag omission almost valid code) and within a full HTML file.
These are opposite situations.
I don't understand it at all. From the point of view of a blind screen reader user, hidden and aria-hidden is the same.
However, I have now understood that labels should not be hidden, but unfortunately I often see it in my everyday test routine and would therefore recommend an explicit note in the ARIA document.
Regardless of whether it is recommended or not, I would still find an explanation of hidden nodes useful. For which elements are they output?
- aria-labelledby
- aria-describedby
- label for
- enclosing label
- legend in fieldset
- figcaption in figure
- caption in table
- ...
When are they output:
- Method (aria-hidden, display:none, hidden, visibility:hidden)
- Location (at the element itself, at the child element, at the descendant element, at the ancestor element)
Please use: https://github.com/w3c/accname/issues/57#issuecomment-529048546
I would still find an explanation of hidden nodes useful
In that case I would implore you to draft a proposal text for this. Either in the form of a PR or in this comment thread.
We appreciate your input. But you have to understand that these things would be solved a lot quicker if we had more people come up with actual copy for this.
Sure, I'm happy to do that. Since I don't speak English and only translate with google translator, someone would have to revise the wording afterwards.
We are more than willing to do that. Having a starting point would be a massive help.
@JAWS-test, based on our discussion in FreedomScientific/VFO-standards-support#251, I think most of your confusion comes from reading the AccName spec and not quite understanding it. If you read only the APG naming section, and do not read the AccName spec, I think you will have a more clear and accurate understanding.
When it comes to providing an accessible name, there is only one way to reference hidden content - aria-labelledby. I think the APG makes that pretty clear. If you do not agree, then please ttell us exactly what part of the APG makes you think there might be another way.
Based on your feedback, I think we need to make only two small refinements to the aria-labelledby and aria-describedby sections in the APG:
- directly address the effect (or lack of effect) of aria-hidden on the name calculation.
- Clearly state that hidden descendants of a node referenced by aria-labelledby are left out of the accessible name.
However, There is one aspect of w3c/accname#57 that I am not certain is fully resolved -- whether the name calculation should be different when aria-labeledby references a node that is hidden as a result of an ancestor being hidden. I think that is an ARIA WG issue. So, we need documented consensus on that before an exception for implicit hiding could be added to the APG.
Do you agree that these are the changes we need to make?
I don’t think there should be a difference between a difference between IDreffing an element that is hidden because it itself is hidden or because an ancestor is. The element is still in the DOM and accessibility tree (and thus available to use).
As a comparison: if you hide a bunch of SVG icons in an SVG-element and then hide said SVG-element you can still reference the icons. I don’t think there should be a difference.
@mcking65
Do you agree that these are the changes we need to make?
Yes, I agree.
I think most of your confusion comes from reading the AccName spec and not quite understanding it.
First of all the confusion comes from the fact that I have to test with screenreader and notice that the output of hidden content is implemented very differently. During my test, I have to specify where the error came from: From the developer (violation of WCAG) or from the browser (violation of UAAG). So I look into the primary source to get names and this is AccName. But it's also true: This specification is very hard to understand.