You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have tested the issue with the latest version of the product
Issue Description
The following checks:
non-empty-placeholder (used by the label rule)
non-empty-value (used by the input-button-name rule)
non-empty-title (used by many *-name rules)
button-has-visible-text (used by the button-name rule)
...currently work by just checking the specific attribute/content they're associated with, ignoring other context. However, it turns out that in some browsers (notably Chrome), the presence of an empty <label> (either implicitly or explicitly linked) will result in these cases being ignored during accessible name calculations. We think this is likely an HTML-AAM violation on Chrome and Safari's parts, but for accessibility-supported purposes, axe-core should respect the least-functional of the fallback behaviors (Chrome's).
I verified that this applies to at least the label, button-name, and input-button-name rules, but note that this probably applies to the other rules that rely on non-empty-title as well (we'll need to add integration tests of that as part of this update)
Note that we'll also want to make corresponding updates to axe's own accessible name calculations, in addition to those specific checks.
Standard interpretation
HTML-AAM §4.1.1 step 3 is consistent with this for title attributes:
Otherwise use the associated label element or elements accessible name(s) - if more than one label is associated; concatenate by DOM order, delimited by spaces.
If the accessible name is still empty, then: use the control's title attribute.
If none of the above yield a usable text string there is no accessible name.
The word "Otherwise" in step 4 is a bit ambiguous, but based on the PR introducing the language, I think it was probably meant to be read similarly to step 3 (ie, as if "Otherwise" were replaced with "If the accessible name is still empty, then: "), which would also be consistent with the current label behavior.
Accessibility Supported status
Unfortunately, the accessibility supported state isn't really consistent with any reasonable interpretation of the standard. Firefox falls back like the label rule expects, but Chrome never fallsand Safari will treat elements with empty <label>s as having empty accessible names in most cases, even if a non-empty placeholder or title is present:
All 10 of the cases above should be violations, since at least one of our accessibility-supported browser combos report empty accessible names for them.
Note that the lack of fallback here only applies to empty <label> elements! All 3 browsers do fall back from empty aria-label and aria-labelledby cases to titles and placeholders:
At the check level, I think the simplest fix would probably be to update the 4 checks in question to return false if an implicit or explicit label is present, which a custom check message explaining why they're inapplicable.
If we write the integration tests and find that actually there are some cases where the current behavior with non-empty-title is correct, we could instead consider something similar to the exiting "none": ["hidden-explicit-label"] check config in the label rule, adding a special check that just reports on this specific incompatibility. I think that'd probably result in worse check messaging in the unaffected cases, though; I think it'd be better to avoid adding more verbosity to those rules' remediation messages, they're already a bit dense.
Suggested accessible name calculation fixes
I think for this it'd be cleaner to do it a bit differently from the checks and closer to how it seems like Chrome is operating in practice. Currently, accessible-text-virtual.js and native-text-alternative.js both contain reduce calls that iterate over the name calculation steps and treat cases where a step returns '' as meaning "fall back to the next step". Since it seems like the chrome behavior really boils down to "if the name from <label> is empty, treat it as a special halting empty name", I'd lean towards updating those core loops to support steps indicating a similar concept, maybe something like a Symbol('halting-empty-string') that is understood to exit-fast from the steps, and update the labelText naming method implementation to return that if it sees a present-but-empty case.
Other updates
We'll want to audit everywhere else our label, labelVirtual, and labelText functions are called to double check if there are any other cases repeating name calculation logic that need similar updates
The text was updated successfully, but these errors were encountered:
dbjorge
changed the title
Accessible name calculation should not allow fallback from empty labels to placeholder/title/value attributes
Accessible name calculation should not allow fallback from empty <label>s
Oct 22, 2024
Product
axe-core
Product Version
4.10.1
Latest Version
Issue Description
The following checks:
non-empty-placeholder
(used by thelabel
rule)non-empty-value
(used by theinput-button-name
rule)non-empty-title
(used by many*-name
rules)button-has-visible-text
(used by thebutton-name
rule)...currently work by just checking the specific attribute/content they're associated with, ignoring other context. However, it turns out that in some browsers (notably Chrome), the presence of an empty
<label>
(either implicitly or explicitly linked) will result in these cases being ignored during accessible name calculations. We think this is likely an HTML-AAM violation on Chrome and Safari's parts, but for accessibility-supported purposes, axe-core should respect the least-functional of the fallback behaviors (Chrome's).I verified that this applies to at least the
label
,button-name
, andinput-button-name
rules, but note that this probably applies to the other rules that rely onnon-empty-title
as well (we'll need to add integration tests of that as part of this update)Note that we'll also want to make corresponding updates to axe's own accessible name calculations, in addition to those specific checks.
Standard interpretation
HTML-AAM §4.1.1 step 3 is consistent with this for
title
attributes:The word "Otherwise" in step 4 is a bit ambiguous, but based on the PR introducing the language, I think it was probably meant to be read similarly to step 3 (ie, as if "Otherwise" were replaced with "If the accessible name is still empty, then: "), which would also be consistent with the current
label
behavior.Accessibility Supported status
Unfortunately, the accessibility supported state isn't really consistent with any reasonable interpretation of the standard. Firefox falls back like the
label
rule expects, but Chrome never fallsand Safari will treat elements with empty<label>
s as having empty accessible names in most cases, even if a non-empty placeholder or title is present:The accessible names as reported by browsers are:
fail15
""
""
"placeholder value"
fail16
""
"placeholder value"
"placeholder value"
fail17
""
""
"title value"
fail18
""
""
"title value"
fail5
""
""
"title value"
fail6
""
""
"title value"
fail7
""
""
"content"
fail8
""
"content"
"content"
fail5
""
""
"value attr"
fail6
""
"value attr"
"value attr"
Expectation
All 10 of the cases above should be violations, since at least one of our accessibility-supported browser combos report empty accessible names for them.
Actual
All 10 of those cases pass
How to Reproduce
See above
Additional context
Original report
See this axe-community slack thread. Thanks @pattonwebz for the original report!
aria-label
/aria-labelledby
out-of-scopeNote that the lack of fallback here only applies to empty
<label>
elements! All 3 browsers do fall back from emptyaria-label
andaria-labelledby
cases to titles and placeholders:pass18
"placeholder value"
"placeholder value"
"placeholder value"
pass19
"placeholder value"
"placeholder value"
"placeholder value"
pass20
"title value"
"title value"
"title value"
pass21
"title value"
"title value"
"title value"
Suggested check fixes
At the check level, I think the simplest fix would probably be to update the 4 checks in question to return
false
if an implicit or explicit label is present, which a custom check message explaining why they're inapplicable.If we write the integration tests and find that actually there are some cases where the current behavior with
non-empty-title
is correct, we could instead consider something similar to the exiting"none": ["hidden-explicit-label"]
check config in thelabel
rule, adding a special check that just reports on this specific incompatibility. I think that'd probably result in worse check messaging in the unaffected cases, though; I think it'd be better to avoid adding more verbosity to those rules' remediation messages, they're already a bit dense.Suggested accessible name calculation fixes
I think for this it'd be cleaner to do it a bit differently from the checks and closer to how it seems like Chrome is operating in practice. Currently,
accessible-text-virtual.js
andnative-text-alternative.js
both containreduce
calls that iterate over the name calculation steps and treat cases where a step returns''
as meaning "fall back to the next step". Since it seems like the chrome behavior really boils down to "if the name from<label>
is empty, treat it as a special halting empty name", I'd lean towards updating those core loops to support steps indicating a similar concept, maybe something like aSymbol('halting-empty-string')
that is understood to exit-fast from the steps, and update thelabelText
naming method implementation to return that if it sees a present-but-empty case.Other updates
We'll want to audit everywhere else our
label
,labelVirtual
, andlabelText
functions are called to double check if there are any other cases repeating name calculation logic that need similar updatesThe text was updated successfully, but these errors were encountered: