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
When is hidden content taken into calculation of name and description? #57
Comments
I understood before testing and before the discussion with @mcking65 (FreedomScientific/standards-support#251)
Since the test and the discussion, I no longer know exactly what the specification actually wants to say. In addition, the specification leaves open the labeling method for which the rule applies (see above: List of labeling methods). |
Hi, The only attributes that are permitted to reference hidden elements are aria-labelledby and aria-describedby. Also, this is only true if the referenced element is explicitly hidden using CSS display:none or visibility:hidden, or the HTML5 hidden attribute. However, if the ancestor element of the referenced element is hidden instead, making the referenced element implicitly hidden, then it will not be exposed. This decision goes back to prior discussions we had regarding this subject in the ARIA WG, where we agreed this would be the most intuitive course to document going forward. In contrast, if a referenced element includes hidden children, whether by CSS or the hidden attribute or the aria-hidden attribute, then those hidden elements will not be included in the computation. You can try out these various combinations on the live test page at Simply add id="test" to the markup that you want to compute the accessible name for by pasting the code in the edit field at the end of the page, then activate the Paste & Test button, which will load the markup and compute the name for the referenced element. Also, if your markup includes focusable elements, the accessible name and description property values will automatically be computed as you tab between each focusable element after you render it within the page. |
Hi @accdc |
I tried https://whatsock.github.io/w3c-alternative-text-computation/Editable%20Live%20Input%20AccName%20Test.html and discovered a case that I find strange:
I would have expected accName to be "1," but it'd give out "1 2." The "2" should not belong to the accName because of the aria-hidden=true at the inner span. It also works correctly if the outer span element is not hidden. |
The result of
I also find surprising: "1" because you wrote indirectly that it does not apply to aria-hidden |
@accdc commented:
Bryan, If I understand, you are saying that in the following code, the first input has a name and the second one does not.
Can you point to where and when the WG made a decision to do this? I don't recall when we may have gone in this direction. I don't understand the purpose. To me, it seems like a very odd querk to throw into the algorithm, and it makes it even more mysterious . It feels counter to what would be intuitively expected. I don't see language in the definition of aria-labelledby or aria-describedby to support it. For that matter, there is no language in the spec that even suggests hidden content may be referenced, which seems like a major oversight. |
Based on the discussion in the 5 May 2020 teleconference a summary of this issue: In general the Effect on Accessible Name Calculation for hidden descendants of a visible node referenced in an
|
Descendant Hiding Technique | accname Calculation | Special Cases |
---|---|---|
HTML hidden attribute |
hidden descendant node and all of its descendants are not included | none |
CSS display: none |
The hidden descendant node and all of its descendants are not included | none |
CSS visibility: hidden |
The hidden descendant node and all of its descendants are not included | Any descendant nodes of the hidden node that are made visible through visibility: visible are included in the accessible name calculation |
ARIA aria-hidden: true |
The descendant node not included in the accessibility tree and all of its descendants are not included | Depends on resolution of Issue 1256 |
Hi, I've updated the AccName Prototype to reflect the WG decision to ignore both implicit and explicitly hidden states on elements directly referenced by aria-labelledby and aria-describedby, regardless if the referenced element is hidden or if one of its parent elements is hidden instead. It also takes into account if a child element is explicitly hidden as well, such as when aria-hidden="true" is used, which should be ignored as documented in the AccName algorithm for recursive processing. Example:
accName: "Field Name" This may need to be clarified within the spec text. |
I'm sorry to add a diverging opinion... It seems that, from the point of view of UA implementation, it's near impossible to tell if a node is explicitly hidden or if it's hidden because its parent is. This information kind of "goes away" in early stages of stylesheet processing, because it's considered redundant. For example, these two pieces of markup are equivalent after the initial processing:
As a consequence, iterating over Bryan's example above:
Firefox current output is: "This is a description. This should stay hidden. And this should stay hidden too.", and Chromium will do the same soon (part of an ongoing refactor). In general, if accname is calculated through an aria-labelledby relation, and the referenced node is hidden, all of its children will be included in the calculation, regardless they are explicitly hidden or not (because that information is gone). We might be able to make a separate case for aria-hidden... In which the output would be: "This is a description. And this should stay hidden too." |
Do you think that browsers are not able to recognize nested hidden information correctly and thus the specification would have to be adjusted? Or would it be acceptable to require browsers to make this distinction? The current version of Chrome is currently still able to do this. The error you describe occurs entirely in Firefox and only partially in Chrome. |
@JAWS-test I've been working on Chromium's accname code for a while, trying to fix some cases we are doing wrong there. At the same time, I tried to enhance results for hidden elements to what I thought was more "consistent" (e.g. https://crbug.com/1204042), and found out the reasons why Chromium and Firefox have the output they have now. Going back to the previous example:
Chromium's current output for description is: "This is a description. And this should stay hidden too." Firefox's is: "This is a description. This should stay hidden. And this should stay hidden too." I'm suggesting that the spec should be adjusted to what browsers do in this case. We might still keep one way to hide a node for accname inside a hidden tree, using aria-hidden, like Chromium does right now; I suppose that could be doable in Firefox too. |
@jaragunde The specification is actually very clear:
I.e. in your example the description should be: "This is a description". So it also says https://whatsock.github.io/w3c-alternative-text-computation/Editable%20Live%20Input%20AccName%20Test.html If the browsers agree on a different approach, perhaps the specification can be adapted (but I can't decide that, other people have to comment on that). |
TL;DR: I agree with what @JAWS-test just said. Whether or not we like what's in the spec, I think what's there (with respect to this issue) is quite clear. Given Case 1:
Case 2:
Case 3:
Case 4:
As for implementing what is currently in the spec and this comment from @jaragunde:
I don't think it matters why it's hidden. I think what matters is, again, checking if it's directly referenced via
Makes sense to me. In both cases I think the name should be "Rich's button". The first example is like my Case 1. The author is saying that they really, really mean to keep the span out of the name calculation. The second example is like my Case 2: That We could update the AccName spec to say something in the ballpark of:
The impact of that change would be the following:
I don't know if that's what authors would expect given the cases above. Thoughts? Also, I think implementing something like that would be harder because now user agents would have to do some checks for nodes which are not explicitly hidden, i.e. by a property on that node. You couldn't just check that node's element's |
Sometimes bringing a spec into alignment with reality makes a lot of sense. In this particular case, I'm afraid I disagree. Look at specific case:
I would think that adding explicit hiding on the And, yeah, I get that user agent code might not currently be able to distinguish if a given node is explicitly hidden or hidden via inheritance. But I think fixing that in the user agents is better and more consistent with what I imagine authors expect. And right now (i.e. without making the change I tossed out for discussion above), I would think your test case should be fixable by what I stated in my previous comment: Get the |
@joanmarie Now I was surprised myself: I always read Accname as saying that nested elements not marked as hidden become part of the accessible namen when the ancestor element marked with hidden is referenced with aria-labelledby.
In my opinion it is not exactly stated in the specification who is right now. This should be added! |
@JAWS-test: I think your reading is what is the spirit of the spec. But I don't believe that's what the spec actually states. More specifically, Step 2A states:
So question 1: What does "directly referenced" mean exactly? Given:
The And here's the definition of "hidden" in the ARIA spec:
Taking my example above, the So if we hit step 2A and Will we hit step 2A? Of course! 😁 Step 1: And that brings us to Step 2A with a hidden node that is not directly referenced by |
@joanmarie You are absolutely right. If you read the specification carefully, it is exactly as you say. Unfortunately, I didn't read it that closely and always just thought how it could be meant and how it also seems logical. The question now would be whether to adjust the specification to allow descendant elements within hidden areas to also contribute to the Accessible Name/Description (because that would make sense and most would expect it that way) or to leave it as is |
Adding some historical context... The original intent of this feature was to supply text for screen-readers (accessibility tree) that was hidden from visual users. It's sort of the opposite of aria-hidden, which hides things from the accessibility tree while leaving it for visual users. <label class="hidden" id="lbl1">foo</label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo" <label class="hidden" id="lbl1">foo <span>bar</span></label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo bar" <label id="lbl1">foo <span class="hidden">bar</span></label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo bar" <label class="hidden" id="lbl1">foo <span>bar <span>baz</span></span></label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo bar baz" <label class="hidden" id="lbl1">foo <span class="hidden">bar</span></label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo bar". <label class="hidden" id="lbl1">foo <span aria-hidden="true">bar</span></label>
<input id="inp1" aria-labelledby="foo"> accname for inp1 is "foo" |
@cyns Your examples are not easy to follow, because the source code was marked so that it is not visible |
I've edited @cyns comment to escape the html. |
Weird… and interesting that all three engines have that behavior. |
Hmmm… Nested hidden ( > $0
< <p>
"foo "
<span id="test1" hidden>bar</span>
<span id="test2" style="visibility: hidden;">baz</span>
" bop"
</p>
> $0.innerText
< "foo bop" This might be exactly what authors expect… |
Not exactly what authors would expect, but this seems consistent between engines. > $0.outerHTML
< "<p>
rendered text node
<span>descendant element</span>
<span hidden>display:none</span>
<span style='visibility: hidden;'>visibility:hidden</span>
<span aria-hidden=true>aria-hidden</span>
rendered text node
</p>"
> $0.innerText
< "rendered text node descendant element aria-hidden rendered text node" ⬆️ When element is rendered, only the rendered, visible text contents are returned via > $0.hidden = true
< true
> $0.innerText
< "rendered text node descendant element display:none visibility:hidden aria-hidden rendered text node" ⬆️ All text contents concatenated when element not rendered via > $0.hidden = false
< false
> $0.style.visibility = "hidden"
< "hidden"
> $0.innerText
< "" ⬆️ All text contents omitted when element not rendered via |
For reference here is the spec text https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute |
Thanks for the link to the spec. The behavior of
Where:
An element with
Where "rendered text collection steps" say:
The value of 'visibility' is 'hidden', hence it returns items, which is empty because we had just started. |
Hi, This is proposed spec text at the moment, which hopefully will have implementor review if not feedback by the time of our next meeting regarding this on Aug 19. |
I missed this before. In this example, only the display:none has an innerText, but I would have expected visibility:hidden innerText to behave the same.
Therefore, this approach will break labels where authors thought that visibility:hidden was an acceptable way to hide a label. Thoughts? Can we still rescue this innerText approach? |
I think the way to do that would be to leave it as |
@cookiecrook visibility:hidden/collapse were the only unexpected ones, and returned ''. In these cases we can't use the innerText algorithm. |
Why not? Perfect is the enemy of the good. I understand that some results were unexpected, including visibility:hidden and nested display:none. I’m suggesting there is benefit to using the existing innerText algorithm anyway. Interoperability being the main one. If there’s a quirk in the innerText algorithm that behaves consistently between engines but is unexpected by authors, maybe we can agree on how the algorithm for innerText should change. If we can’t agree on how innerText should change, keep innerText the way it is. 🤷 Either way, we’d have browser interop and it would not require further update to the ARIA spec. |
I'm not aware that innerText behaves differently between browsers. |
Correct. But the AccName computation does behave differently between browsers. If we standardize the AccName algorithm to use innerText in these contexts, we'll have interoperability for those portions of the computation.
I'm aware Google has tools able to determine that prevalence. Is there precedence for providing that info into the public discussion? If so, would you be willing to gather and share it? |
I can look into it. I would still have the concern that even if it's not
prevalent, what if it's important to that user at that moment, e.g. they
are trying to schedule a vaccination or pay their loan, etc. I was thinking
that the path of least resistance, where I won't get lots of regression
bugs filed, is to just avoid this code path for visibility hidden/collapse.
We can still get most of the code simplification benefits in Blink anyway.
|
Do you have an edit suggestion for #137? |
I'll tak to @cynthia Shelly ***@***.***> about it today.
…On Wed, Sep 22, 2021 at 2:29 PM James Craig ***@***.***> wrote:
Do you have an edit suggestion for #137
<#137>?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#57 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAKQAZWGQX4SMC5VHJQURB3UDIOBVANCNFSM4IUCCLQQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
|
From the call, the examples requested are: Rendered:
Not Rendered:
|
Do we need a separate example for "rendered as |
@aleventhal is working on a test implementation without innerText in Chrome, and will comment or update the PR (to replace the innerText reference in the current PR) once that's reasonably complete. |
Specifically, @jaragunde is working on it. |
The comments in AXObject::IsHiddenForTextAlternativeCalculation() implied that, in case of obtaining a name out of a hidden subtree via aria-labelledby or -describedby relations, it would exclude those nodes that were explicitly hidden. This is an interpretation that does not match the spec and, moreover, it was not possible to implement. We cannot really tell if a node is directly hidden by style or if it inherited that property, because that information gets optimized out in the early steps of style computation and it would be costly to retrieve. The above was discussed extensively at: w3c/accname#57. In particular, our problems to find out if a node was explicitly hidden are shared with WebKit, and Firefox does not work like that either. The existing code was actually working, but it was not doing what code comments implied to. I think the combination of these three facts was what made the existing code work, although for wrong reasons: * This condition in AXObject::IsHiddenForTextAlternativeCalculation(): return IsHiddenViaStyle() && (!ParentObject() || !ParentObject()->IsHiddenViaStyle()); It detected the topmost node that gets hidden, preventing the name from contents algorithm from entering it when traversing a visible subtree. * During an aria-labelledby traversal of a hidden subtree, the above condition was always false, which effectively exposed all nodes. * This condition in AXObject::AriaTextAlternative(): if (!aria_label_or_description_root && IsHiddenForTextAlternativeCalculation()) return String(); Combined with the previous one, it detected when the target of an aria-labelledby relation was explicitly hidden and its parent was not, exposing its contents. So we can say this is more a legibility change than anything else. This patch makes explicit that we contribute all nodes inside a hidden target of an aria-labelledby or -describedby relation, and changes the conditions to detect this situation, removing the faulty heuristics. Bug: 1255036 Change-Id: I80fac3ce883f9c165841636db3d6e4c8fa884260 AX-relnotes: simplify conditions for accessible name calculation Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3312490 Reviewed-by: Daniel Libby <dlibby@microsoft.com> Reviewed-by: Aaron Leventhal <aleventhal@chromium.org> Commit-Queue: Jacobo Aragunde Pérez <jaragunde@igalia.com> Cr-Commit-Position: refs/heads/main@{#949109}
The comments in AXObject::IsHiddenForTextAlternativeCalculation() implied that, in case of obtaining a name out of a hidden subtree via aria-labelledby or -describedby relations, it would exclude those nodes that were explicitly hidden. This is an interpretation that does not match the spec and, moreover, it was not possible to implement. We cannot really tell if a node is directly hidden by style or if it inherited that property, because that information gets optimized out in the early steps of style computation and it would be costly to retrieve. The above was discussed extensively at: w3c/accname#57. In particular, our problems to find out if a node was explicitly hidden are shared with WebKit, and Firefox does not work like that either. The existing code was actually working, but it was not doing what code comments implied to. I think the combination of these three facts was what made the existing code work, although for wrong reasons: * This condition in AXObject::IsHiddenForTextAlternativeCalculation(): return IsHiddenViaStyle() && (!ParentObject() || !ParentObject()->IsHiddenViaStyle()); It detected the topmost node that gets hidden, preventing the name from contents algorithm from entering it when traversing a visible subtree. * During an aria-labelledby traversal of a hidden subtree, the above condition was always false, which effectively exposed all nodes. * This condition in AXObject::AriaTextAlternative(): if (!aria_label_or_description_root && IsHiddenForTextAlternativeCalculation()) return String(); Combined with the previous one, it detected when the target of an aria-labelledby relation was explicitly hidden and its parent was not, exposing its contents. So we can say this is more a legibility change than anything else. This patch makes explicit that we contribute all nodes inside a hidden target of an aria-labelledby or -describedby relation, and changes the conditions to detect this situation, removing the faulty heuristics. Bug: 1255036 Change-Id: I80fac3ce883f9c165841636db3d6e4c8fa884260 AX-relnotes: simplify conditions for accessible name calculation Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3312490 Reviewed-by: Daniel Libby <dlibby@microsoft.com> Reviewed-by: Aaron Leventhal <aleventhal@chromium.org> Commit-Queue: Jacobo Aragunde Pérez <jaragunde@igalia.com> Cr-Commit-Position: refs/heads/main@{#949109} NOKEYCHECK=True GitOrigin-RevId: 276cddcc13f2fdd921dc9331f576058a77229bb1
Unfortunately for me (as well as for the browser manufacturers and developers of assistive technology: FreedomScientific/standards-support#251) the procedure for determining labeling and description is too complex (https://w3c.github.io/accname/#terminology) and I would therefore like to know how to proceed with hidden content according to the specification.
For which label types is hidden content output valid?
When does it apply?
If I'm not the only one who doesn't see this directly from the specification, I'd ask you to be more precise in the specification and possibly give some examples of when hidden content is output and when not.
See also: w3c/aria-practices#1136
The text was updated successfully, but these errors were encountered: