alfa
alfa copied to clipboard
Elements whose implicit role depends on the presence of an accessible name might not be correctly handled
An example is the <section>
element which should have an implicit role of region
if the element also has an accessible name: https://w3c.github.io/html-aam/#el-section. Alfa does not yet handle cases like these correctly though:
https://github.com/Siteimprove/alfa/blob/45e77ac69e6547c4f13273ac36761318108d0574/packages/alfa-aria/src/feature.ts#L511-L514
The reason is the circularity between the role and accessible name computations; to determine the role of an element we might need to first determine its accessible name and to determine its accessible name we might need to first determine its role. The best way to deal with this seems to be to make it possible to break the accessible name computation into configurable steps to allow callers to only enable a subset of the steps taken in determining the accessible name.
Elements whose implicit role depend on name:
-
<aside>
-
<form>
-
<section>
Rules that are affected by this:
- R40 (targets
region
, may be<section>
- R55, R56 (targets
landmark
, may be either<form>
or<section>
) - R57 (search for
landmark
).
We currently handle these cases directly in the rules, through the hasIncorrectRoleWithoutName
predicate. This is not a very satisfactory solution and the problem starts creeping in several rules 😕
Surprisingly, Chrome also fails to handle this case correctly and exposes <section>
elements with a role of region
regardless of whether or not they have an accessible name. Safari never assigns implicit roles to <section>
elements, despite the WebKit code seemingly saying otherwise, while Firefox acts according to spec. Browsers... 🤦
For reference:
-
Chromium (
content/browser/accessibility/browser_accessibility_cocoa.mm
) -
WebKit (
Source/WebCore/accessibility/AccessibilityRenderObject.cpp
)Edit: It appears that the Safari Accessibility pane might simply be playing tricks. When a
<section>
element has anaria-label
oraria-labelledby
attribute the element is announced as a "group", yet no role shows up in the inspector.
This may be influenced by #307.
It appears that Chrome might actually just be dealing with this at a different layer, possibly to get around the same issue as we're facing? There's a method BrowserAccessibility::GetLocalizedStringForLandmarkType()
, which I imagine gets the localised string to announce for landmark types, that does a name check for the region
and section
(equivalent to region
in Chromium it seems) roles: content/browser/accessibility/browser_accessibility.cc#L1892-L1895
Here are some test cases to try out:
-
<section>Hello world</section>
-
<section aria-label>Hello world</section>
-
<section aria-label=" ">Hello world</section>
-
<section aria-label="Label">Hello world</section>
Results on my end:
-
<section>Hello world</section>
Chrome + VoiceOver: "hello world" Safari + VoiceOver: "hello world" Firefox + VoiceOver: "hello world"
-
<section aria-label>Hello world</section>
Chrome + VoiceOver: "hello world" Safari + VoiceOver: "hello world" Firefox + VoiceOver: "hello world"
-
<section aria-label=" ">Hello world</section>
Chrome + VoiceOver: "region" Safari + VoiceOver: "space, region" Firefox + VoiceOver: "hello world"
-
<section aria-label="Label">Hello world</section>
Chrome + VoiceOver: "label, region" Safari + VoiceOver: "label, region" Firefox + VoiceOver: "label, region"
For now, we'll handle the case of <section>
elements in SIA-R40 directly (#678), but on second thought I'll not consider that a solution to this issue. Seeing how Firefox is currently the only browser test that behaves correctly, we might borrow some pointers from its implementation.
To temporarily fix this issue and #307, we have created the predicate hasRoleDependingOnName
in #1108
I think that I encountered something like this issue on a customer's page. But it might not be exactly the same issue.
Here is a reconstruction of the customer's HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<title>x</title>
</head>
<body>
<aside>
some text
</aside>
<main>x
</main>
</body>
</html>
The HTML above fails R57. That is incorrect, I think, because https://www.w3.org/TR/html-aam-1.0/#el-aside-ancestorbodymain states that "aside (scoped to the body or main element)" has the implicit role of complementary and has no accessible name requirement.
The HTML below passes R57.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<title>x</title>
</head>
<body>
<aside aria-label="x">
some text
</aside>
<main>x
</main>
</body>
</html>
Yes, that's part of it. I messed up when I hacked around it in this commit 🙈
@dan-tripp-siteimprove a fix is on its way. Should be part of v0.60