@surea11y/core 1.7.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +103 -1
- package/README.md +157 -54
- package/docs/ACT_RULE_MAPPING.md +8 -7
- package/docs/API_STABILITY.md +18 -5
- package/docs/BINDING_AUTHORS_GUIDE.md +2 -2
- package/docs/CI_INTEGRATIONS.md +43 -0
- package/docs/DESIGN_CHALLENGES.md +97 -3
- package/docs/EARL.md +2 -2
- package/docs/ENGINE_OPTIONS.md +81 -3
- package/docs/I18N.md +62 -20
- package/docs/JUNIT.md +73 -0
- package/docs/LIMITATIONS.md +1 -0
- package/docs/OUTPUT_SCHEMA.md +19 -6
- package/docs/REPORT.md +7 -2
- package/docs/RULE_AUTHORING.md +73 -6
- package/docs/RULE_CATALOG.md +139 -116
- package/docs/RULE_EXAMPLES.md +2189 -0
- package/docs/RULE_HELPERS.md +62 -5
- package/docs/RULE_TAXONOMY.md +2 -2
- package/docs/SARIF.md +2 -1
- package/docs/WCAG_CONFORMANCE.md +56 -3
- package/package.json +34 -11
- package/profiles/index.js +14 -0
- package/src/checks/automatic/area-alt-present.js +87 -31
- package/src/checks/automatic/aria-braille-equivalent.js +25 -7
- package/src/checks/automatic/aria-hidden-focus.js +74 -18
- package/src/checks/automatic/aria-prohibited-attr.js +17 -4
- package/src/checks/automatic/aria-required-attr.js +29 -0
- package/src/checks/automatic/aria-role-name-present.js +19 -2
- package/src/checks/automatic/aria-valid-attr-value.js +28 -16
- package/src/checks/automatic/autocomplete-valid.js +26 -11
- package/src/checks/automatic/avoid-inline-spacing.js +105 -40
- package/src/checks/automatic/button-name-present.js +2 -1
- package/src/checks/automatic/canvas-text-alternative-present.js +105 -14
- package/src/checks/automatic/combobox-name-present.js +34 -51
- package/src/checks/automatic/contrast-computable.js +35 -4
- package/src/checks/automatic/contrast-enhanced.js +4 -4
- package/src/checks/automatic/contrast-minimum.js +45 -11
- package/src/checks/automatic/css-orientation-lock.js +152 -30
- package/src/checks/automatic/definition-list-children-valid.js +67 -23
- package/src/checks/automatic/deprecated-elements-not-used.js +43 -38
- package/src/checks/automatic/dialog-name-present.js +28 -9
- package/src/checks/automatic/duplicate-id.js +6 -2
- package/src/checks/automatic/identical-iframes-same-purpose.js +4 -4
- package/src/checks/automatic/iframe-focusable-content.js +7 -4
- package/src/checks/automatic/iframe-title-unique.js +36 -81
- package/src/checks/automatic/input-image-alt-present.js +32 -20
- package/src/checks/automatic/label-in-name.js +40 -13
- package/src/checks/automatic/language-page-present.js +12 -6
- package/src/checks/automatic/link-in-text-block.js +272 -60
- package/src/checks/automatic/link-name-present.js +13 -5
- package/src/checks/automatic/list-children-valid.js +18 -1
- package/src/checks/automatic/listbox-name-present.js +19 -49
- package/src/checks/automatic/listitem-parent-valid.js +4 -3
- package/src/checks/automatic/meta-refresh-no-exceptions.js +3 -3
- package/src/checks/automatic/page-title-present.js +16 -4
- package/src/checks/automatic/progressbar-name-present.js +11 -1
- package/src/checks/automatic/role-img-text-alternative-present.js +9 -5
- package/src/checks/automatic/searchbox-name-present.js +32 -49
- package/src/checks/automatic/server-side-image-map-absent.js +48 -28
- package/src/checks/automatic/slider-name-present.js +38 -52
- package/src/checks/automatic/spinbutton-name-present.js +32 -49
- package/src/checks/automatic/target-size-minimum.js +0 -11
- package/src/checks/automatic/td-has-header.js +41 -5
- package/src/checks/automatic/text-spacing-content-loss.js +548 -0
- package/src/checks/automatic/textbox-name-present.js +32 -49
- package/src/checks/automatic/valid-lang.js +15 -10
- package/src/checks/manual/area-alt-quality-manual.js +113 -31
- package/src/checks/manual/canvas-text-alternative-quality-manual.js +0 -2
- package/src/checks/manual/css-focus-indicator-suppressed-manual.js +23 -10
- package/src/checks/manual/css-hidden-focus.js +215 -7
- package/src/checks/manual/form-control-label-quality-manual.js +109 -5
- package/src/checks/manual/heading-order-manual.js +9 -1
- package/src/checks/manual/heading-quality-manual.js +143 -9
- package/src/checks/manual/img-alt-decorative-manual.js +6 -3
- package/src/checks/manual/input-image-alt-quality-manual.js +81 -13
- package/src/checks/manual/link-name-quality-manual.js +130 -4
- package/src/checks/manual/media-transcript-present-manual.js +65 -8
- package/src/checks/manual/mouse-only-event-handlers-manual.js +66 -5
- package/src/checks/manual/no-autoplay-audio-manual.js +93 -6
- package/src/checks/manual/p-as-heading-manual.js +89 -44
- package/src/checks/manual/page-title-patterns-manual.js +77 -8
- package/src/checks/manual/skip-link-manual.js +42 -14
- package/src/checks/manual/table-fake-caption-manual.js +32 -1
- package/src/checks/manual/video-caption-manual.js +47 -24
- package/src/checks/manual-review.js +0 -4
- package/src/core.js +14285 -2219
- package/src/coverage/en301549-map.js +187 -0
- package/src/coverage/standards.js +279 -0
- package/src/coverage/wcag-facets.js +1119 -0
- package/src/coverage/wcag-version-map.js +101 -0
- package/src/en301549.js +33 -0
- package/src/junit.js +321 -0
- package/src/profile-kit.js +163 -0
- package/src/report.js +343 -74
- package/src/sarif.js +34 -3
- package/src/wcag.js +105 -0
- package/surea11y.browser.js +5 -4
- package/surea11y.i18n.de.js +1 -1
- package/surea11y.i18n.es.js +1 -1
- package/surea11y.i18n.fr.js +1 -1
- package/surea11y.i18n.ja.js +3 -0
- package/src/checks/manual/area-alt-decorative-manual.js +0 -255
package/docs/RULE_CATALOG.md
CHANGED
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
Generated from the compiled engine's own catalog (`getChecksCatalog()`/`getRulesCatalog()`) and each rule's source header. Run `node scripts/generate-rule-catalog.js` after `npm run build` to regenerate this file whenever rules change. Do not hand-edit.
|
|
4
4
|
|
|
5
|
-
**133 rules total:
|
|
5
|
+
**133 rules total: 80 automatic (WCAG-normative, can return `fail`), 53 manual (advisory/judgment-required, capped at `cantTell`). 107 carry at least one formal WCAG Success Criterion mapping.**
|
|
6
6
|
|
|
7
7
|
The tables below are an index; [rule reference](#rule-reference) carries each rule's description, what it applies to and what it expects.
|
|
8
8
|
|
|
9
9
|
See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`severity` mean on a scan result, and [`WCAG_CONFORMANCE.md`](./WCAG_CONFORMANCE.md) for how these roll up to an SC-level conformance claim. For WCAG-facet-level coverage-gap tracking (which parts of an SC are and aren't automatable yet), see `coverage/coverage-report.md` instead: that one is organized by facet, this one by rule.
|
|
10
10
|
|
|
11
|
-
## Automatic rules (
|
|
11
|
+
## Automatic rules (80), can return `fail`
|
|
12
12
|
|
|
13
13
|
| Rule ID | Title | WCAG SC | Level | Confidence | Default severity |
|
|
14
14
|
|---|---|---|---|---|---|
|
|
15
|
-
| [`area-alt-present`](#area-alt-present) | <area> must have an
|
|
15
|
+
| [`area-alt-present`](#area-alt-present) | <area> must have an accessible name | 1.1.1 | A | high | serious |
|
|
16
16
|
| [`aria-allowed-attr`](#aria-allowed-attr) | aria-* attributes must be permitted for the element’s role | 4.1.2 | A | medium | moderate |
|
|
17
17
|
| [`aria-allowed-role`](#aria-allowed-role) | Explicit role must be permitted for its host element | — | — | high | moderate |
|
|
18
18
|
| [`aria-braille-equivalent`](#aria-braille-equivalent) | aria-braillelabel/aria-brailleroledescription must have a non-braille equivalent | 4.1.2 | A | high | moderate |
|
|
@@ -40,7 +40,7 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
40
40
|
| [`contrast-minimum`](#contrast-minimum) | Text meets minimum color contrast (AA) | 1.4.3 | AA | high | serious |
|
|
41
41
|
| [`css-orientation-lock`](#css-orientation-lock) | CSS must not lock the page to a single orientation | 1.3.4 | AA | high | serious |
|
|
42
42
|
| [`definition-list-children-valid`](#definition-list-children-valid) | Description lists must be structured correctly | 1.3.1 | A | high | serious |
|
|
43
|
-
| [`deprecated-elements-not-used`](#deprecated-elements-not-used) |
|
|
43
|
+
| [`deprecated-elements-not-used`](#deprecated-elements-not-used) | Scrolling <marquee> content must be possible to pause, stop, or hide | 2.2.2 | A | high | serious |
|
|
44
44
|
| [`dialog-name-present`](#dialog-name-present) | Dialogs have an accessible name | 4.1.2 | A | high | serious |
|
|
45
45
|
| [`dlitem-parent-valid`](#dlitem-parent-valid) | Description-list items must be inside a description list | 1.3.1 | A | high | serious |
|
|
46
46
|
| [`duplicate-id`](#duplicate-id) | IDs must be unique | 4.1.1 | A | high | moderate |
|
|
@@ -53,17 +53,17 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
53
53
|
| [`identical-iframes-same-purpose`](#identical-iframes-same-purpose) | Frames with the same name embed the same resource | 4.1.2 | A | medium | moderate |
|
|
54
54
|
| [`iframe-focusable-content`](#iframe-focusable-content) | Frames with tabindex="-1" must not contain focusable content | 2.1.1 | A | high | moderate |
|
|
55
55
|
| [`iframe-name-present`](#iframe-name-present) | Frames have an accessible name | 4.1.2 | A | high | serious |
|
|
56
|
-
| [`iframe-title-unique`](#iframe-title-unique) | Frame
|
|
56
|
+
| [`iframe-title-unique`](#iframe-title-unique) | Frame title uniqueness (deprecated) | 4.1.2 | A | high | moderate |
|
|
57
57
|
| [`img-alt-present`](#img-alt-present) | <img> must have an alt attribute | 1.1.1 | A | high | serious |
|
|
58
58
|
| [`input-image-alt-present`](#input-image-alt-present) | <input type="image"> must have an alt attribute | 1.1.1 | A | high | serious |
|
|
59
59
|
| [`label-in-name`](#label-in-name) | Label in Name: accessible name contains visible text | 2.5.3 | A | high | serious |
|
|
60
60
|
| [`link-in-text-block`](#link-in-text-block) | Links in text blocks must be distinguishable from surrounding text without relying on color alone | 1.4.1 | A | high | serious |
|
|
61
|
-
| [`link-name-present`](#link-name-present) | Links have an accessible name | 4.1.2 | A | high | serious |
|
|
61
|
+
| [`link-name-present`](#link-name-present) | Links have an accessible name | 2.4.4, 4.1.2 | A | high | serious |
|
|
62
62
|
| [`list-children-valid`](#list-children-valid) | Lists must only directly contain list items | 1.3.1 | A | high | serious |
|
|
63
63
|
| [`listbox-name-present`](#listbox-name-present) | Listboxes have an accessible name | 4.1.2 | A | high | serious |
|
|
64
64
|
| [`listitem-parent-valid`](#listitem-parent-valid) | List items must be inside a list container | 1.3.1 | A | high | serious |
|
|
65
65
|
| [`menuitem-name-present`](#menuitem-name-present) | Menu items have an accessible name | 4.1.2 | A | high | serious |
|
|
66
|
-
| [`meta-refresh-no-exceptions`](#meta-refresh-no-exceptions) | Page must not use a meta refresh
|
|
66
|
+
| [`meta-refresh-no-exceptions`](#meta-refresh-no-exceptions) | Page must not use a timed meta refresh (AAA) | 2.2.4, 3.2.5 | AAA | high | moderate |
|
|
67
67
|
| [`meta-refresh-timing-absent`](#meta-refresh-timing-absent) | Page must not use a timed meta refresh | 2.2.1 | A | high | serious |
|
|
68
68
|
| [`meta-viewport-zoom-enabled`](#meta-viewport-zoom-enabled) | Viewport meta tag must not disable zoom | 1.4.4 | AA | high | serious |
|
|
69
69
|
| [`meter-name-present`](#meter-name-present) | Meters have an accessible name | 1.1.1 | A | high | serious |
|
|
@@ -75,7 +75,7 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
75
75
|
| [`progressbar-name-present`](#progressbar-name-present) | Progress bars have an accessible name | 1.1.1 | A | high | serious |
|
|
76
76
|
| [`role-img-text-alternative-present`](#role-img-text-alternative-present) | [role="img"/"graphics-symbol"/"graphics-document"] must have an accessible text alternative | 1.1.1 | A | high | serious |
|
|
77
77
|
| [`searchbox-name-present`](#searchbox-name-present) | Searchboxes have an accessible name | 4.1.2 | A | high | serious |
|
|
78
|
-
| [`server-side-image-map-absent`](#server-side-image-map-absent) |
|
|
78
|
+
| [`server-side-image-map-absent`](#server-side-image-map-absent) | Server-side image maps must have a keyboard-operable alternative | 2.1.1 | A | high | serious |
|
|
79
79
|
| [`slider-name-present`](#slider-name-present) | Sliders have an accessible name | 4.1.2 | A | high | serious |
|
|
80
80
|
| [`spinbutton-name-present`](#spinbutton-name-present) | Spinbuttons have an accessible name | 4.1.2 | A | high | serious |
|
|
81
81
|
| [`summary-name-present`](#summary-name-present) | Summary elements have an accessible name | 4.1.2 | A | high | serious |
|
|
@@ -86,19 +86,19 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
86
86
|
| [`table-th-has-data-cells`](#table-th-has-data-cells) | <th> elements must describe at least one data cell | 1.3.1 | A | high | moderate |
|
|
87
87
|
| [`target-size-minimum`](#target-size-minimum) | Pointer targets must be at least 24x24px large, or leave sufficient distance to other targets | 2.5.8 | AA | medium | serious |
|
|
88
88
|
| [`td-has-header`](#td-has-header) | Data cells in large tables must have an associated header | 1.3.1 | A | high | serious |
|
|
89
|
+
| [`text-spacing-content-loss`](#text-spacing-content-loss) | Text stays readable when the user increases text spacing | 1.4.12 | AA | medium | serious |
|
|
89
90
|
| [`textbox-name-present`](#textbox-name-present) | Textboxes have an accessible name | 4.1.2 | A | high | serious |
|
|
90
91
|
| [`tooltip-name-present`](#tooltip-name-present) | Tooltips have an accessible name | 4.1.2 | A | high | serious |
|
|
91
92
|
| [`treeitem-name-present`](#treeitem-name-present) | Tree items have an accessible name | 4.1.2 | A | high | serious |
|
|
92
93
|
| [`valid-lang`](#valid-lang) | Element lang attribute must be syntactically valid | 3.1.2 | AA | high | moderate |
|
|
93
94
|
| [`video-poster-text-alternative-present`](#video-poster-text-alternative-present) | <video> poster must have a text alternative | 1.1.1 | A | medium | serious |
|
|
94
95
|
|
|
95
|
-
## Manual rules (
|
|
96
|
+
## Manual rules (53), advisory, capped at `cantTell`
|
|
96
97
|
|
|
97
98
|
| Rule ID | Title | WCAG SC | Level | Confidence | Default severity |
|
|
98
99
|
|---|---|---|---|---|---|
|
|
99
100
|
| [`accesskeys`](#accesskeys) | accesskey values must be unique | — | — | medium | minor |
|
|
100
|
-
| [`area-alt-
|
|
101
|
-
| [`area-alt-quality`](#area-alt-quality) | <area> alt text must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
101
|
+
| [`area-alt-quality`](#area-alt-quality) | <area> text alternative must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
102
102
|
| [`aria-checked-state-mismatch`](#aria-checked-state-mismatch) | Native checkbox/radio aria-checked should match its actual state | 4.1.2 | A | medium | moderate |
|
|
103
103
|
| [`aria-text`](#aria-text) | role="text" elements should have no focusable descendants | — | — | medium | minor |
|
|
104
104
|
| [`bypass-blocks-present`](#bypass-blocks-present) | Page must provide a way to bypass repeated blocks | 2.4.1 | A | medium | moderate |
|
|
@@ -118,7 +118,7 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
118
118
|
| [`img-alt-decorative`](#img-alt-decorative) | Excluded <img>/<canvas>/<svg> must be decorative (manual review) | 1.1.1 | A | medium | minor |
|
|
119
119
|
| [`img-alt-quality`](#img-alt-quality) | <img> alt text must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
120
120
|
| [`input-image-alt-decorative`](#input-image-alt-decorative) | <input type="image"> with alt="" must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
121
|
-
| [`input-image-alt-quality`](#input-image-alt-quality) | <input type="image">
|
|
121
|
+
| [`input-image-alt-quality`](#input-image-alt-quality) | <input type="image"> text alternative must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
122
122
|
| [`label-title-only`](#label-title-only) | Form controls should not use title as their only label | — | — | medium | minor |
|
|
123
123
|
| [`landmark-banner-is-top-level`](#landmark-banner-is-top-level) | Banner landmark must be top-level | — | — | medium | minor |
|
|
124
124
|
| [`landmark-complementary-is-top-level`](#landmark-complementary-is-top-level) | Complementary landmark must be top-level | — | — | medium | minor |
|
|
@@ -136,7 +136,7 @@ See [`OUTPUT_SCHEMA.md`](./OUTPUT_SCHEMA.md) for what `type`/`confidence`/`sever
|
|
|
136
136
|
| [`mouse-only-event-handlers`](#mouse-only-event-handlers) | Pointer-only inline event handlers should have a keyboard-reachable equivalent | 2.1.1 | A | low | moderate |
|
|
137
137
|
| [`no-autoplay-audio`](#no-autoplay-audio) | Autoplaying audio should provide a pause/stop or volume-control mechanism | 1.4.2 | A | low | moderate |
|
|
138
138
|
| [`object-text-alternative-quality`](#object-text-alternative-quality) | <object> text alternative must be appropriate (manual review) | 1.1.1 | A | medium | minor |
|
|
139
|
-
| [`p-as-heading`](#p-as-heading) |
|
|
139
|
+
| [`p-as-heading`](#p-as-heading) | Text styled to look like a heading should probably be a real heading | 1.3.1 | A | low | minor |
|
|
140
140
|
| [`page-has-heading-one`](#page-has-heading-one) | Page should have a level-one heading | — | — | medium | minor |
|
|
141
141
|
| [`page-title-patterns`](#page-title-patterns) | Page title patterns that may be insufficiently descriptive | 2.4.2 | A | medium | minor |
|
|
142
142
|
| [`password-paste-enabled`](#password-paste-enabled) | Authentication fields must not block pasting | 3.3.8 | AA | medium | serious |
|
|
@@ -157,14 +157,14 @@ Composite rules aren't individually authored. They're generated rollups over the
|
|
|
157
157
|
|
|
158
158
|
| Composite ID | Title | Description | WCAG SC | Level | # atomic rules rolled up |
|
|
159
159
|
|---|---|---|---|---|---|
|
|
160
|
-
| `wcag-1.1.1-non-text-content` | Non-text content: text alternatives | Rollup of checks ensuring non-text content has an appropriate text alternative. | 1.1.1 | A |
|
|
160
|
+
| `wcag-1.1.1-non-text-content` | Non-text content: text alternatives | Rollup of checks ensuring non-text content has an appropriate text alternative. | 1.1.1 | A | 21 |
|
|
161
161
|
| `wcag-1.2.1-audio-only-video-only-prerecorded` | Audio-only and video-only (prerecorded): transcript | Rollup of checks for transcript availability for prerecorded audio-only/video-only media. | 1.2.1 | A | 1 |
|
|
162
162
|
| `wcag-1.2.2-captions-prerecorded` | Captions (Prerecorded) | Rollup of checks for captions-track evidence on prerecorded video. | 1.2.2 | A | 1 |
|
|
163
163
|
| `wcag-1.3.1-info-and-relationships` | Info and Relationships | Rollup of checks ensuring information, structure, and relationships conveyed through presentation are programmatically determinable. | 1.3.1 | A | 14 |
|
|
164
164
|
| `wcag-1.3.4-orientation` | Orientation | Rollup of checks ensuring content does not restrict its view to a single display orientation. | 1.3.4 | AA | 1 |
|
|
165
165
|
| `wcag-1.3.5-identify-input-purpose` | Identify Input Purpose | Rollup of checks ensuring the autocomplete attribute correctly identifies input purpose. | 1.3.5 | AA | 1 |
|
|
166
166
|
| `wcag-1.4.1-use-of-color` | Use of Color | Rollup of checks ensuring color is not used as the only visual means of conveying information. | 1.4.1 | A | 1 |
|
|
167
|
-
| `wcag-1.4.12-text-spacing` | Text Spacing | Rollup of checks ensuring
|
|
167
|
+
| `wcag-1.4.12-text-spacing` | Text Spacing | Rollup of checks ensuring text spacing can be increased without losing content. | 1.4.12 | AA | 2 |
|
|
168
168
|
| `wcag-1.4.2-audio-control` | Audio Control | Rollup of checks for a pause/stop or volume-control mechanism on autoplaying audio. | 1.4.2 | A | 1 |
|
|
169
169
|
| `wcag-1.4.3-contrast-minimum` | Contrast: minimum | Rollup of checks for minimum text contrast. | 1.4.3 | AA | 2 |
|
|
170
170
|
| `wcag-1.4.4-resize-text` | Resize Text | Rollup of checks ensuring the viewport meta tag does not prevent users from zooming text up to 200%. | 1.4.4 | AA | 1 |
|
|
@@ -177,7 +177,7 @@ Composite rules aren't individually authored. They're generated rollups over the
|
|
|
177
177
|
| `wcag-2.4.1-bypass-blocks` | Bypass Blocks | Rollup of checks ensuring the page provides a way to bypass repeated blocks of content. | 2.4.1 | A | 1 |
|
|
178
178
|
| `wcag-2.4.2-page-titled` | Page titled | Rollup of checks ensuring documents have a meaningful page title. | 2.4.2 | A | 2 |
|
|
179
179
|
| `wcag-2.4.3-focus-order` | Focus order | Rollup of checks ensuring focus moves through content in a meaningful order. | 2.4.3 | A | 1 |
|
|
180
|
-
| `wcag-2.4.4-link-purpose-in-context` | Link Purpose (In Context) | Rollup of checks flagging links whose text alone is a known non-descriptive/generic phrase. | 2.4.4 | A |
|
|
180
|
+
| `wcag-2.4.4-link-purpose-in-context` | Link Purpose (In Context) | Rollup of checks flagging links with no accessible name, or whose text alone is a known non-descriptive/generic phrase. | 2.4.4 | A | 2 |
|
|
181
181
|
| `wcag-2.4.6-headings-and-labels` | Headings and Labels | Rollup of checks flagging headings whose text is a placeholder rather than a description of the content that follows. | 2.4.6 | AA | 2 |
|
|
182
182
|
| `wcag-2.4.7-focus-visible` | Focus visible | Rollup of checks ensuring keyboard focus is not hidden and remains perceivable. | 2.4.7 | AA | 4 |
|
|
183
183
|
| `wcag-2.4.9-link-purpose-link-only` | Link Purpose (Link Only) | Rollup of checks ensuring links with the same accessible name serve the same purpose (AAA). | 2.4.9 | AAA | 1 |
|
|
@@ -208,41 +208,29 @@ Checks that no two elements on the page share the same accesskey attribute value
|
|
|
208
208
|
|
|
209
209
|
**Expectation.** Every accesskey value on the page is unique. Duplicate accesskeys make keyboard-shortcut activation ambiguous: only one of the elements sharing the key can actually be reached by it, and which one is browser/platform-dependent.
|
|
210
210
|
|
|
211
|
-
### `area-alt-decorative`
|
|
212
|
-
|
|
213
|
-
**<area> with alt="" must be decorative (manual review)**
|
|
214
|
-
|
|
215
|
-
manual · WCAG 1.1.1 (A) · confidence medium · default severity minor
|
|
216
|
-
|
|
217
|
-
Flags <area> elements with empty alt for human review that they are decorative/non-informative.
|
|
218
|
-
|
|
219
|
-
**Applies to.** Applies to <area> elements whose alt attribute is present but empty once trimmed, the markup that declares a hotspot decorative. The <area> must belong to a <map> that an <img usemap> actually references, and both that <img> and the <area> itself must be included in the accessibility tree; an <area> in an unused map is out of scope. role="presentation"/"none" takes an element out unless it is focusable.
|
|
220
|
-
|
|
221
|
-
**Expectation.** Human review is required to confirm that the provided text alternative is accurate and appropriate.
|
|
222
|
-
|
|
223
211
|
### `area-alt-present`
|
|
224
212
|
|
|
225
|
-
**<area> must have an
|
|
213
|
+
**<area> must have an accessible name**
|
|
226
214
|
|
|
227
215
|
automatic · WCAG 1.1.1 (A) · confidence high · default severity serious
|
|
228
216
|
|
|
229
|
-
Checks that <area> elements
|
|
217
|
+
Checks that <area> elements have a non-empty accessible name via alt, aria-label/aria-labelledby, or title.
|
|
230
218
|
|
|
231
|
-
**Applies to.** Applies to <area> elements that: 1) are in a <map> that is referenced by an <img usemap>, AND 2) the referencing <img> is
|
|
219
|
+
**Applies to.** Applies to <area> elements that: 1) are in a <map> that is referenced by an <img usemap>, AND 2) carry a non-empty href (an <area> with no href is not a hyperlink at all per the HTML spec, and has nothing for this rule to name), AND 3) the referencing <img> is actually rendered (hidden/display:none/ visibility exclude it; aria-hidden does not, since <area> is not a DOM descendant of <img>), AND 4) the <area> itself is eligible in the accessibility tree. hidden, display:none and inert on the <area> or its <map> do not exclude it: neither element generates a box, so a real browser's image-map hit-testing ignores all three there (verified against Chromium and Firefox); only those mechanisms on a genuine ancestor of the whole <img>+<map> pairing do.
|
|
232
220
|
|
|
233
|
-
**Expectation.** Each applicable <area> element has
|
|
221
|
+
**Expectation.** Each applicable <area> element has a non-empty accessible name, from alt, aria-label/aria-labelledby, or title. An <area> in a used map is always a link, so alt="" is not decorative here as it is on <img>: an empty alt fails the same as a missing one unless another mechanism names it.
|
|
234
222
|
|
|
235
223
|
### `area-alt-quality`
|
|
236
224
|
|
|
237
|
-
**<area>
|
|
225
|
+
**<area> text alternative must be appropriate (manual review)**
|
|
238
226
|
|
|
239
227
|
manual · WCAG 1.1.1 (A) · confidence medium · default severity minor
|
|
240
228
|
|
|
241
|
-
Flags <area> elements with non-empty alt
|
|
229
|
+
Flags <area> elements with a non-empty text alternative (alt, aria-label, aria-labelledby or title) for human review of appropriateness.
|
|
242
230
|
|
|
243
|
-
**Applies to.** Applies to <area> elements
|
|
231
|
+
**Applies to.** Applies to <area> elements that get a non-empty text alternative from any source: aria-labelledby (resolving to text), aria-label, alt or title. The <area> must carry a non-empty href (otherwise it is not a hyperlink at all per the HTML spec) and belong to a <map> that an <img usemap> actually references; an <area> in an unused map is out of scope. The referencing <img> must actually be rendered (hidden/display:none/ visibility exclude it; aria-hidden does not, since <area> is not a DOM descendant of <img>), and the <area> itself must be eligible: hidden, display:none and inert on the <area> or its <map> do not exclude it, since neither generates a box and a real browser's image-map hit-testing ignores all three there (verified against Chromium and Firefox); only those mechanisms on a genuine ancestor of the whole <img>+<map> pairing do. role="presentation"/"none" takes an element out unless it is focusable.
|
|
244
232
|
|
|
245
|
-
**Expectation.** Human review is required to confirm that the provided text alternative is accurate and appropriate.
|
|
233
|
+
**Expectation.** Human review is required to confirm that the provided text alternative is accurate and appropriate. Each occurrence lists every source present (data.details.sources), so the reviewer checks each one: a title or aria-label that is not the name still reaches some users.
|
|
246
234
|
|
|
247
235
|
### `aria-allowed-attr`
|
|
248
236
|
|
|
@@ -358,6 +346,8 @@ No element with aria-hidden="true" may itself be focusable, and no focusable ele
|
|
|
358
346
|
|
|
359
347
|
- Focusability is computed via ctx.helpers.getFocusableInfo (native + tabindex + contenteditable).
|
|
360
348
|
- Elements that are not rendered (e.g., display:none, visibility:hidden, [hidden]) are excluded.
|
|
349
|
+
- Disabled controls are not focusable, including those disabled by an ancestor <fieldset disabled> (matched with :disabled).
|
|
350
|
+
- <area href> has no box of its own, so it is judged by the <img usemap> that uses its <map>: it counts as focusable when such an image is rendered and not inert.
|
|
361
351
|
- Elements hidden via CSS in ways that still allow keyboard focus (e.g., opacity:0, off-screen, clip) remain in-scope and will be flagged when focusable.
|
|
362
352
|
|
|
363
353
|
### `aria-prohibited-attr`
|
|
@@ -368,7 +358,7 @@ automatic · WCAG 4.1.2 (A) · confidence high · default severity moderate
|
|
|
368
358
|
|
|
369
359
|
Checks that aria-label/aria-labelledby are not present on WAI-ARIA roles whose specification explicitly prohibits ARIA naming (e.g. generic, emphasis, strong, paragraph).
|
|
370
360
|
|
|
371
|
-
**Applies to.** Applies to (a) elements whose explicit, valid role is one of the ARIA 1.2 roles with a documented "Prohibited ARIA States and Properties" list for naming attributes (pure text-semantics / non-naming structural roles: caption, code, deletion, emphasis, generic, insertion, mark, none, paragraph, presentation, strong, subscript, suggestion, superscript, time), and (b) elements with no role at all: a curated set of native HTML tags verified to carry no implicit role (see ROLELESS_NATIVE_TAGS below), or any autonomous custom element (a hyphenated, author-defined tag per the Custom Elements spec; see isRolelessCustomElementTag below). In both cases, only elements that also carry aria-label or aria-labelledby.
|
|
361
|
+
**Applies to.** Applies to (a) elements whose explicit, valid role is one of the ARIA 1.2 roles with a documented "Prohibited ARIA States and Properties" list for naming attributes (pure text-semantics / non-naming structural roles: caption, code, deletion, emphasis, generic, insertion, mark, none, paragraph, presentation, strong, subscript, suggestion, superscript, time), plus a native <caption> with no valid explicit role, whose implicit role is caption, and (b) elements with no role at all: a curated set of native HTML tags verified to carry no implicit role (see ROLELESS_NATIVE_TAGS below), or any autonomous custom element (a hyphenated, author-defined tag per the Custom Elements spec; see isRolelessCustomElementTag below). In both cases, only elements that also carry aria-label or aria-labelledby.
|
|
372
362
|
|
|
373
363
|
**Expectation.** Prohibited attributes must not be present on (a); for (b), the naming attribute is at best unreliable (nothing accessible-name-aware to hang it off) and at worst silently ignored by assistive technology. See the roleless-branch implementation note below for the confidence split this produces.
|
|
374
364
|
|
|
@@ -392,7 +382,7 @@ automatic · WCAG 4.1.2 (A) · confidence high · default severity serious
|
|
|
392
382
|
|
|
393
383
|
Checks that elements with an explicit role carry every unambiguous, context-independent required aria-* state/property for that role (e.g. role="checkbox" must have aria-checked).
|
|
394
384
|
|
|
395
|
-
**Applies to.** Applies to elements with an explicit, valid, non-abstract role that is also one of the small set of roles with a documented, context- independent required state/property (checkbox, combobox, heading, menuitemcheckbox, menuitemradio, meter, radio, scrollbar, separator, slider, switch) -- except when that explicit role is identical to the element's own native/implicit role (ACT 4e8ab6: e.g. <input type="checkbox" role="checkbox">, which is exempt because the native control's own state exposure already covers it; no aria-checked is required. helpers.aria.getNativeRoleForElement resolves this).
|
|
385
|
+
**Applies to.** Applies to elements with an explicit, valid, non-abstract role that is also one of the small set of roles with a documented, context- independent required state/property (checkbox, combobox, heading, menuitemcheckbox, menuitemradio, meter, radio, scrollbar, separator, slider, switch) -- except when that explicit role is identical to the element's own native/implicit role (ACT 4e8ab6: e.g. <input type="checkbox" role="checkbox">, which is exempt because the native control's own state exposure already covers it; no aria-checked is required. helpers.aria.getNativeRoleForElement resolves this). A native <input type="checkbox"> or <input type="radio"> with another checkable role (switch, menuitemcheckbox, menuitemradio, or checkbox on a radio and the reverse) is in scope, but its aria-checked counts as supplied: the browser exposes the input's own checked state (HTML-AAM), so it passes without the attribute.
|
|
396
386
|
|
|
397
387
|
**Expectation.**
|
|
398
388
|
|
|
@@ -435,7 +425,7 @@ Checks that the ARIA roles WAI-ARIA requires an accessible name for expose a non
|
|
|
435
425
|
|
|
436
426
|
**Applies to.** Applies to elements whose role attribute is exactly one of grid, meter, progressbar, radiogroup or tree, and that are included in the accessibility tree. Membership is decided by WAI-ARIA's own "Accessible Name Required: True" characteristic, not by whether a role merely permits a name: tablist, toolbar, menu, menubar and scrollbar are name-from-author roles the spec does not require a name for, and are out of scope. meter and progressbar are also covered by meter-name-present and progressbar-name-present, which map to SC 1.1.1; this rule is what gives those two roles their 4.1.2 coverage.
|
|
437
427
|
|
|
438
|
-
**Expectation.** The element has a non-empty aria-label, an aria-labelledby that resolves to non-empty text, or a non-empty title. Every role in the set is name-from-author-only, so descendant text is not accepted: a labelled child inside a composite widget would otherwise pass the container that has no name of its own.
|
|
428
|
+
**Expectation.** The element has a non-empty aria-label, an aria-labelledby that resolves to non-empty text, or a non-empty title. Every role in the set is name-from-author-only, so descendant text is not accepted: a labelled child inside a composite widget would otherwise pass the container that has no name of its own. The name the HTML host element gives itself counts too, since the browser still computes it under the role: the first child <legend> of a <fieldset>, the first child <caption> of a <table>, and an associated <label> on a labelable element such as <progress> or <meter>.
|
|
439
429
|
|
|
440
430
|
### `aria-roles-valid`
|
|
441
431
|
|
|
@@ -488,7 +478,7 @@ Checks that every recognized aria-* attribute has a value conforming to its WAI-
|
|
|
488
478
|
|
|
489
479
|
**Applies to.** Applies to any element carrying at least one recognized aria-* attribute (unrecognized attribute names are aria-valid-attr's concern, not evaluated here).
|
|
490
480
|
|
|
491
|
-
**Expectation.** Each attribute's value conforms to its WAI-ARIA-declared value type: boolean ("true"/"false"), tristate ("true"/"false"/"mixed"), a token from a fixed enumerated set, an integer, a real number, or an ID reference (list) that resolves to an existing element in the document. Per ACT 6a7281's own applicability ("any state or property that is NOT empty"), an explicitly empty value, including a bare boolean-style attribute with no "=value" at all, e.g. `aria-checked` alone, is out of scope for every value type, not a violation: a common, deliberate pattern in templated markup (e.g. React conditionally rendering `aria-describedby={hasError ? errorId : ''}`).
|
|
481
|
+
**Expectation.** Each attribute's value conforms to its WAI-ARIA-declared value type: boolean ("true"/"false"), tristate ("true"/"false"/"mixed"), a token from a fixed enumerated set, an integer (within the range WAI-ARIA sets for it), a real number, or an ID reference (list) that resolves to an existing element in the document. Per ACT 6a7281's own applicability ("any state or property that is NOT empty"), an explicitly empty value, including a bare boolean-style attribute with no "=value" at all, e.g. `aria-checked` alone, is out of scope for every value type, not a violation: a common, deliberate pattern in templated markup (e.g. React conditionally rendering `aria-describedby={hasError ? errorId : ''}`).
|
|
492
482
|
|
|
493
483
|
### `autocomplete-valid`
|
|
494
484
|
|
|
@@ -498,9 +488,9 @@ automatic · WCAG 1.3.5 (AA) · confidence high · default severity moderate
|
|
|
498
488
|
|
|
499
489
|
Checks that a non-empty autocomplete attribute is "on"/"off" or a well-formed autofill detail token list.
|
|
500
490
|
|
|
501
|
-
**Applies to.** Applies to form controls (input, select, textarea) with a non-empty autocomplete attribute.
|
|
491
|
+
**Applies to.** Applies to form controls (input, select, textarea) with a non-empty autocomplete attribute. Disabled controls (the disabled attribute, including a control disabled by a disabled fieldset ancestor, or aria-disabled="true") and input types with a fixed value are exempt, as in ACT 73f2c2.
|
|
502
492
|
|
|
503
|
-
**Expectation.** The value is "on"/"off" alone, or a well-formed autofill detail token list: an optional "section-*" token, then an optional "shipping"/"billing" token, then an optional contact-modality token (home/work/mobile/fax/pager
|
|
493
|
+
**Expectation.** The value is "on"/"off" alone, or a well-formed autofill detail token list: an optional "section-*" token, then an optional "shipping"/"billing" token, then an optional contact-modality token (home/work/mobile/fax/pager), then exactly one recognized field-name token (name, email, street-address, cc-number, tel, ...), optionally followed by "webauthn". A malformed value means the field is not reliably identified for assistive technology that relies on autocomplete to describe the expected input purpose.
|
|
504
494
|
|
|
505
495
|
### `avoid-inline-spacing`
|
|
506
496
|
|
|
@@ -536,7 +526,7 @@ Checks that buttons expose a non-empty accessible name.
|
|
|
536
526
|
|
|
537
527
|
**Applies to.** Applies to <button>, <input type="button">, <input type="submit">, <input type="reset"> and elements with role="button", where the element is included in the accessibility tree. role="presentation"/"none" takes an element out of scope unless a global ARIA attribute or focusability restores its role, per presentational roles conflict resolution.
|
|
538
528
|
|
|
539
|
-
**Expectation.** The element has a non-empty accessible name. A programmatic name is taken first (aria-labelledby, aria-label, an associated <label>, title). Failing that, an <input> button falls back to its value attribute, and type="submit"/type="reset" fall back to the user agent's own "Submit"/"Reset" default, which is why those two are never nameless. Failing both, a button whose role is name-from-content falls back to its subtree text, counting each descendant's own name (an <img alt>, aria-label or title) rather than only text nodes.
|
|
529
|
+
**Expectation.** The element has a non-empty accessible name. A programmatic name is taken first (aria-labelledby, aria-label, an associated <label>, title). Failing that, an <input> button falls back to its value attribute, and type="submit"/type="reset" fall back to the user agent's own "Submit"/"Reset" default, which is why those two are never nameless. Failing both, a button whose role is name-from-content falls back to its subtree text, counting each descendant's own name (an <img alt>, aria-label, an <svg>'s <title> child, or title) rather than only text nodes.
|
|
540
530
|
|
|
541
531
|
### `bypass-blocks-present`
|
|
542
532
|
|
|
@@ -560,7 +550,12 @@ Checks that <canvas> elements provide a text alternative via fallback cont
|
|
|
560
550
|
|
|
561
551
|
**Applies to.** Applies to <canvas> elements included in the accessibility tree. Hidden elements are excluded whether or not they are focusable.
|
|
562
552
|
|
|
563
|
-
**Expectation.**
|
|
553
|
+
**Expectation.**
|
|
554
|
+
|
|
555
|
+
Each applicable <canvas> provides a text alternative via fallback content or an accessible name, with two exceptions:
|
|
556
|
+
|
|
557
|
+
- role="img" (first role token) makes the canvas's children presentational and its name comes from the author only, so fallback content does not count: aria-labelledby, aria-label or title must name it.
|
|
558
|
+
- role="none"/"presentation" marks the canvas decorative, and it passes. The role is ignored (presentational role conflict) when the canvas is focusable or carries aria-label/aria-labelledby, and the canvas is then judged like any other.
|
|
564
559
|
|
|
565
560
|
### `canvas-text-alternative-quality`
|
|
566
561
|
|
|
@@ -584,7 +579,7 @@ Checks that elements with role="combobox" expose a non-empty accessible name.
|
|
|
584
579
|
|
|
585
580
|
**Applies to.** Applies to elements carrying role="combobox" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope.
|
|
586
581
|
|
|
587
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="combobox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom combobox widget is not reliably exposed as its name. On a labelable element (<input role="combobox">) an associated <label> counts as well.
|
|
582
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="combobox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom combobox widget is not reliably exposed as its name. On a labelable element (<input role="combobox">) an associated <label> counts as well. On a text-like <input> or a <textarea>, the placeholder counts last (HTML-AAM's final name source): a placeholder-only label is a 3.3.2 question, not a missing name.
|
|
588
583
|
|
|
589
584
|
### `contrast-computable`
|
|
590
585
|
|
|
@@ -628,11 +623,11 @@ Checks that visible text has a contrast ratio of at least 4.5:1 (normal) or 3:1
|
|
|
628
623
|
|
|
629
624
|
manual · WCAG 2.4.7 (AA) · confidence medium · default severity serious
|
|
630
625
|
|
|
631
|
-
Flags elements in the tab order whose focus outline is removed by a :focus/:focus-visible rule with no replacement indicator (border, box-shadow, background, ...) in any
|
|
626
|
+
Flags elements in the tab order whose focus outline is removed, by a :focus/:focus-visible rule or by a rule with no state such as a { outline: none }, with no replacement indicator (border, box-shadow, background, ...) in any focus rule matching them.
|
|
632
627
|
|
|
633
|
-
**Applies to.** Elements in sequential focus navigation (tabbable and rendered) on a page whose accessible stylesheets contain at least one
|
|
628
|
+
**Applies to.** Elements in sequential focus navigation (tabbable and rendered) on a page whose accessible stylesheets contain at least one rule that removes the outline. With no such rule anywhere, every element keeps the user agent's own indicator and there is nothing to check.
|
|
634
629
|
|
|
635
|
-
**Expectation.** No element is matched by a
|
|
630
|
+
**Expectation.** No element is matched by a rule that removes the outline (`outline: none`, `outline: 0`, `outline-color: transparent`, ...) unless some focus rule matching it draws a replacement: a border, box-shadow, background, color change, a positive outline of its own, or a `::before`/`::after` decoration. The removing rule is either a `:focus`/`:focus-visible` rule, or a rule with no state at all (`a { outline: none }`, `* { outline: 0 }`): an author declaration outranks the user agent's focus outline whatever its specificity, so it removes the indicator in the focused state too (WCAG F78).
|
|
636
631
|
|
|
637
632
|
### `css-hidden-focus`
|
|
638
633
|
|
|
@@ -646,11 +641,12 @@ Checks that keyboard-focusable elements are not visually hidden by CSS technique
|
|
|
646
641
|
|
|
647
642
|
**Expectation.**
|
|
648
643
|
|
|
649
|
-
No element should be tabbable while visually hidden (e.g., opacity:0, clipped, off-screen). Notes:
|
|
644
|
+
No element should be tabbable while visually hidden (e.g., opacity:0, clipped, off-screen). An element that CSS brings back into view when it takes focus is not hidden while focused, and is not flagged: the usual skip-link pattern (`.skip { position: absolute; left: -9999px } .skip:focus { left: 0 }`), or a hiding rule that stops applying on focus (`.visually-hidden-focusable:not(:focus) { clip: rect(0 0 0 0) }`). Notes:
|
|
650
645
|
|
|
651
646
|
- This rule intentionally targets CSS techniques that *can* keep an element focusable.
|
|
652
647
|
- Elements removed from rendering (display:none, visibility:hidden, [hidden]) are excluded.
|
|
653
648
|
- The rule uses deterministic heuristics (computed style parsing) and does not rely on layout geometry.
|
|
649
|
+
- The focused style is worked out from the stylesheets, not by focusing the element: a DOM emulator does not restyle `:focus`. Rules whose subject carries `:focus`, `:focus-visible` or `:focus-within` (or an ancestor carries `:focus-within`) are laid over the computed style in document order; a rule written `:not(:focus)` / `:not(:focus-within)` / `:not(:focus-visible)` has its declarations reset to their initial values. Inline style outranks a stylesheet rule unless the rule is `!important`. The overlay ignores specificity among the focus rules, and cross-origin stylesheets cannot be read, so their focus rules are not seen.
|
|
654
650
|
|
|
655
651
|
### `css-orientation-lock`
|
|
656
652
|
|
|
@@ -658,11 +654,11 @@ No element should be tabbable while visually hidden (e.g., opacity:0, clipped, o
|
|
|
658
654
|
|
|
659
655
|
automatic · WCAG 1.3.4 (AA) · confidence high · default severity serious
|
|
660
656
|
|
|
661
|
-
Checks that no @media (orientation: portrait|landscape) rule sets a transform: rotate(...) on the page, a known technique for defeating device orientation.
|
|
657
|
+
Checks that no @media (orientation: portrait|landscape) rule sets a transform: rotate(...) on the page, a known technique for defeating device orientation, and asks about any such rule that hides the page's main content.
|
|
662
658
|
|
|
663
659
|
**Applies to.** Any accessible (same-document, non-cross-origin) stylesheet, inline `<style>` blocks and same-origin `<link>` stylesheets already loaded into `document.styleSheets`.
|
|
664
660
|
|
|
665
|
-
**Expectation.** No `@media (orientation: portrait)` or `@media (orientation: landscape)` block sets a `transform`/`-webkit-transform`/`rotate` rotation of approximately 90 degrees (mod 180, i.e. ~90 or ~270), the well-known technique for visually forcing one orientation regardless of the device's actual orientation, which defeats WCAG 1.3.4's requirement that content not restrict its view to a single display orientation unless that orientation is essential.
|
|
661
|
+
**Expectation.** No `@media (orientation: portrait)` or `@media (orientation: landscape)` block sets a `transform`/`-webkit-transform`/`rotate` rotation of approximately 90 degrees (mod 180, i.e. ~90 or ~270), the well-known technique for visually forcing one orientation regardless of the device's actual orientation, which defeats WCAG 1.3.4's requirement that content not restrict its view to a single display orientation unless that orientation is essential. Such a rotation fails. A second shape is asked about (cantTell): an orientation media block that hides the page's content with `display: none` or `visibility: hidden`, the usual form of WCAG F100 (content replaced by a "rotate your device" message in one orientation). The hidden element counts as the page's content when it is `html` or `body`, the `main` landmark, an ancestor of it, or, on a page without a main landmark, an element holding at least half of the body's text. Whether the orientation is essential, and whether the page stays usable, is left to a person.
|
|
666
662
|
|
|
667
663
|
### `definition-list-children-valid`
|
|
668
664
|
|
|
@@ -672,21 +668,21 @@ automatic · WCAG 1.3.1 (A) · confidence high · default severity serious
|
|
|
672
668
|
|
|
673
669
|
Checks that <dl> elements only directly contain <dt>/<dd> groups (optionally wrapped in one <div>), <script>, <template>, or <style>.
|
|
674
670
|
|
|
675
|
-
**Applies to.** Applies to <dl> elements that have at least one direct element child.
|
|
671
|
+
**Applies to.** Applies to <dl> elements that have at least one direct element child or non-whitespace text directly inside them.
|
|
676
672
|
|
|
677
|
-
**Expectation.** Every direct element child is <dt>, <dd>, <script>, <template>, <style>, or a <div> whose own children are drawn from that same set (a single level of wrapping div is allowed, matching how authors commonly group dt/dd pairs). If the flattened set contains any <dt> or <dd> at all, it must contain BOTH (an unbalanced dt-without-dd or dd-without-dt is invalid). A flattened set with neither is vacuously fine, not a violation (see implementation-notes). Any other direct or wrapped child breaks the description-list semantics assistive technologies rely on.
|
|
673
|
+
**Expectation.** Every direct element child is <dt>, <dd>, <script>, <template>, <style>, or a <div> whose own children are drawn from that same set (a single level of wrapping div is allowed, matching how authors commonly group dt/dd pairs). Non-whitespace text directly inside the <dl> or a wrapping <div> is an invalid child too. If the flattened set contains any <dt> or <dd> at all, it must contain BOTH (an unbalanced dt-without-dd or dd-without-dt is invalid), and read in order it must be groups of one or more <dt> followed by one or more <dd>: a <dd> before the first <dt> has no term, and a <dt> after the last <dd> has no definition. A flattened set with neither is vacuously fine, not a violation (see implementation-notes). Any other direct or wrapped child breaks the description-list semantics assistive technologies rely on.
|
|
678
674
|
|
|
679
675
|
### `deprecated-elements-not-used`
|
|
680
676
|
|
|
681
|
-
**
|
|
677
|
+
**Scrolling <marquee> content must be possible to pause, stop, or hide**
|
|
682
678
|
|
|
683
679
|
automatic · WCAG 2.2.2 (A) · confidence high · default severity serious
|
|
684
680
|
|
|
685
|
-
|
|
681
|
+
Asks, for each obsolete <marquee> element, whether the page offers a way to pause, stop, or hide its auto-scrolling content, since the element itself has none.
|
|
686
682
|
|
|
687
|
-
**Applies to.** Applies to any
|
|
683
|
+
**Applies to.** Applies to any scan scope; whether it contains a <marquee> element is always an answerable question. <marquee> is an obsolete, non-standard HTML element that browsers still render as auto-scrolling text, with no built-in user mechanism to pause, stop, or hide it.
|
|
688
684
|
|
|
689
|
-
**Expectation.**
|
|
685
|
+
**Expectation.** Each <marquee> is reported as cantTell: the scrolling itself is certain, but a page can offer its own pause or stop control (a button calling the element's stop() method, for example), and then failure F16 does not apply. Whether such a control exists is for a person to check. A scope with no <marquee> passes; there is no separate not-applicable case.
|
|
690
686
|
|
|
691
687
|
### `dialog-name-present`
|
|
692
688
|
|
|
@@ -694,9 +690,9 @@ Checks that deprecated, non-standard HTML elements whose blinking/scrolling cont
|
|
|
694
690
|
|
|
695
691
|
automatic · WCAG 4.1.2 (A) · confidence high · default severity serious
|
|
696
692
|
|
|
697
|
-
Checks that elements with role="dialog" or role="alertdialog" expose a non-empty accessible name.
|
|
693
|
+
Checks that dialogs (elements with role="dialog" or role="alertdialog", and native <dialog> elements) expose a non-empty accessible name.
|
|
698
694
|
|
|
699
|
-
**Applies to.** Applies to elements
|
|
695
|
+
**Applies to.** Applies to elements included in the accessibility tree whose role is dialog or alertdialog: an element whose role attribute resolves to one of those roles (the first token that names a concrete ARIA role wins, so role="alertdialog dialog" is an alertdialog), and a native <dialog> whose role attribute is absent or names no concrete role (its implicit role is dialog). A closed <dialog> is hidden and so not in scope.
|
|
700
696
|
|
|
701
697
|
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. Both roles are name-from-author-only, so the heading or body text inside the dialog is not accepted as its name unless aria-labelledby points at it.
|
|
702
698
|
|
|
@@ -722,7 +718,7 @@ Checks that every non-empty id attribute value is unique within its own document
|
|
|
722
718
|
|
|
723
719
|
**Applies to.** Applies to any element carrying a non-empty id attribute. Visibility is irrelevant. A duplicate id breaks the same lookups whether the element renders or not, which is why ACT 3ea0c8 evaluates hidden elements too.
|
|
724
720
|
|
|
725
|
-
**Expectation.** No other element in the same tree carries the same id value. Ids are scoped per document tree and per shadow tree, so the same id inside two different shadow roots is not a duplicate.
|
|
721
|
+
**Expectation.** No other element in the same tree carries the same id value, compared exactly as written (id="a " and id="a" are different ids). Ids are scoped per document tree and per shadow tree, so the same id inside two different shadow roots is not a duplicate.
|
|
726
722
|
|
|
727
723
|
### `duplicate-id-aria`
|
|
728
724
|
|
|
@@ -809,7 +805,7 @@ Flags elements with tabindex >= 0 whose explicit role is a non-interactive st
|
|
|
809
805
|
|
|
810
806
|
manual · WCAG 2.4.6 (AA) · confidence medium · default severity minor
|
|
811
807
|
|
|
812
|
-
Flags a visible form-field label that is a placeholder ("Label", "Field"), or that repeats another field's label with no visible context (heading, legend, or row) telling the two apart.
|
|
808
|
+
Flags a visible form-field label that is a placeholder ("Label", "Field"), or that repeats another field's label with no visible context (heading, legend, or row) telling the two apart. English placeholders are always recognized, and German, Spanish, French or Japanese ones when the field is in that language.
|
|
813
809
|
|
|
814
810
|
**Applies to.** Visible form fields: native `input` (excluding hidden and the button-like types), `select`, `textarea`, or an element with one of the ARIA widget roles ACT cc0f0a lists (checkbox, combobox, listbox, menuitemcheckbox, menuitemradio, radio, searchbox, slider, spinbutton, switch, textbox) that carry a visible programmatic label: a `<label>` association, or the elements `aria-labelledby` points at. A field named only by `aria-label`/`title` has no visible label to judge and is out of scope here (its labelling mechanism is `form-control-programmatic-label-quality`'s concern, its presence `form-control-programmatic-label-present`'s).
|
|
815
811
|
|
|
@@ -882,7 +878,7 @@ manual · no formal WCAG SC mapping · confidence medium · default severity min
|
|
|
882
878
|
|
|
883
879
|
Checks that heading levels increase by at most one at a time in document order.
|
|
884
880
|
|
|
885
|
-
**Applies to.** Applies whenever the page contains two or more heading elements (native <h1>-<h6>, or explicit role="heading" with aria-level; default level 2 per the ARIA spec when aria-level is absent/invalid).
|
|
881
|
+
**Applies to.** Applies whenever the page contains two or more heading elements (native <h1>-<h6>, or explicit role="heading" with aria-level; default level 2 per the ARIA spec when aria-level is absent/invalid). A native <hx> with a valid aria-level (a positive integer) takes that level, as browsers expose it; otherwise it takes its tag level.
|
|
886
882
|
|
|
887
883
|
**Expectation.** In document order, each heading's level is no more than one greater than the highest heading level seen so far. Jumping deeper by more than one level (e.g. an <h1> followed directly by an <h3>, skipping <h2>) breaks the document outline assistive technology users rely on when navigating by heading. Going back to a shallower level at any point is always fine.
|
|
888
884
|
|
|
@@ -892,7 +888,7 @@ Checks that heading levels increase by at most one at a time in document order.
|
|
|
892
888
|
|
|
893
889
|
manual · WCAG 2.4.6 (AA) · confidence medium · default severity minor
|
|
894
890
|
|
|
895
|
-
Flags headings whose accessible name is a placeholder rather than a description of the content that follows: a generic word ("Heading", "Untitled"), a numbered template slot ("Section 2"), a filename, or a URL.
|
|
891
|
+
Flags headings whose accessible name is a placeholder rather than a description of the content that follows: a generic word ("Heading", "Untitled"), a numbered template slot ("Section 2"), a filename, or a URL. English phrases are always recognized, and German, Spanish, French or Japanese ones when the heading is in that language.
|
|
896
892
|
|
|
897
893
|
**Applies to.** Elements with a heading role (native <h1>-<h6>, or any element with an explicit role="heading") that are included in the accessibility tree and have a non-empty accessible name. A heading with no name at all is `empty-heading`'s concern, not this rule's.
|
|
898
894
|
|
|
@@ -908,7 +904,7 @@ Checks that the default language of the page is programmatically declared.
|
|
|
908
904
|
|
|
909
905
|
**Applies to.** Applies to HTML documents with a root <html> element. The rule evaluates the document element only and does not iterate over child nodes. Non-HTML documents or documents without a document element are not applicable.
|
|
910
906
|
|
|
911
|
-
**Expectation.** The <html> element has a lang attribute. The lang attribute is not empty and
|
|
907
|
+
**Expectation.** The <html> element has a lang attribute. The lang attribute is not empty and its primary language subtag (the part before the first hyphen) is a registered language subtag, as ACT bf051a requires. A malformed later subtag (lang="fr-FR-!!") still identifies French, so it passes here; it is a markup validity error, not a missing language.
|
|
912
908
|
|
|
913
909
|
### `html-xml-lang-mismatch`
|
|
914
910
|
|
|
@@ -972,15 +968,15 @@ Checks that <iframe>/<frame> elements expose a non-empty accessible
|
|
|
972
968
|
|
|
973
969
|
### `iframe-title-unique`
|
|
974
970
|
|
|
975
|
-
**Frame
|
|
971
|
+
**Frame title uniqueness (deprecated)**
|
|
976
972
|
|
|
977
973
|
automatic · WCAG 4.1.2 (A) · confidence high · default severity moderate
|
|
978
974
|
|
|
979
|
-
|
|
975
|
+
Deprecated since 1.8.0 and always notApplicable: whether frames sharing a name embed the same resource is checked by identical-iframes-same-purpose.
|
|
980
976
|
|
|
981
|
-
**Applies to.**
|
|
977
|
+
**Applies to.** Nothing. The rule is deprecated and reports notApplicable on every page. Its id stays in the catalog, with meta.deprecated set and deprecation.replacedBy naming the successor, so a runOnly list, a stored baseline or an open Code Scanning alert that holds the id keeps resolving until the file is removed in 2.0.0 (docs/API_STABILITY.md, "Rule-ID deprecation policy").
|
|
982
978
|
|
|
983
|
-
**Expectation.**
|
|
979
|
+
**Expectation.** None. The check this rule used to make, that no two frames share a title attribute, is not a WCAG 4.1.2 requirement: the criterion asks that a frame's name be programmatically determinable, not unique, and ACT rule 4b1c6c accepts identical names on frames that embed equivalent resources. identical-iframes-same-purpose asks the question 4b1c6c does ask, of the computed accessible name, which for a frame is the title attribute unless aria-label or aria-labelledby overrides it.
|
|
984
980
|
|
|
985
981
|
### `image-redundant-alt`
|
|
986
982
|
|
|
@@ -1002,7 +998,7 @@ manual · WCAG 1.1.1 (A) · confidence medium · default severity minor
|
|
|
1002
998
|
|
|
1003
999
|
Flags <img>, <canvas> and <svg> elements excluded from the accessibility tree (aria-hidden, role="none"/"presentation", empty alt, or an unlabeled svg/canvas) for human review that they are purely decorative.
|
|
1004
1000
|
|
|
1005
|
-
**Applies to.** Applies to visible <img>, <canvas> or <svg> elements excluded from the accessibility tree by any of: an aria-hidden ancestor-or-self, an explicit role="none"/"presentation" not overridden by focusability, an <img alt=""> (the native decorative marker, same focusability override), an unlabeled <svg> whose implicit role is graphics-document (no img/graphics-symbol role restatement, aria-name, <title>/<desc>, or focusability), or an unlabeled <canvas> with no explicit role at all. Per ACT e88epe, an element is skipped entirely when any ancestor already has an author-supplied name (aria-label, aria-labelledby, title, or an associated <label>), that ancestor's name is what matters, not this element's exclusion (the common real case: an icon-only button already named via aria-label).
|
|
1001
|
+
**Applies to.** Applies to visible <img>, <canvas> or <svg> elements excluded from the accessibility tree by any of: an aria-hidden ancestor-or-self, an explicit role="none"/"presentation" not overridden by focusability, an <img alt=""> (the native decorative marker, same focusability override; only a literally empty alt, so alt=" " is not one), an unlabeled <svg> whose implicit role is graphics-document (no img/graphics-symbol role restatement, aria-name, <title>/<desc>, or focusability), or an unlabeled <canvas> with no explicit role at all. Per ACT e88epe, an element is skipped entirely when any ancestor already has an author-supplied name (aria-label, aria-labelledby, title, or an associated <label>), that ancestor's name is what matters, not this element's exclusion (the common real case: an icon-only button already named via aria-label).
|
|
1006
1002
|
|
|
1007
1003
|
**Expectation.** Human review is required to confirm the excluded element is purely decorative and conveys no information a user would otherwise miss.
|
|
1008
1004
|
|
|
@@ -1052,19 +1048,19 @@ Checks that <input type="image"> elements provide an alt attribute to supp
|
|
|
1052
1048
|
|
|
1053
1049
|
**Applies to.** Applies to <input type="image"> elements included in the accessibility tree.
|
|
1054
1050
|
|
|
1055
|
-
**Expectation.** Each applicable <input type="image"> element has
|
|
1051
|
+
**Expectation.** Each applicable <input type="image"> element has a non-empty accessible name from aria-labelledby, aria-label, alt or title. An empty name fails, whether alt is missing or empty (alt=""). An author-supplied name that equals a browser default for an image button ("Submit", "Submit Query") is not an empty name: it may describe the button, so it is reported as cantTell for a person to judge.
|
|
1056
1052
|
|
|
1057
1053
|
### `input-image-alt-quality`
|
|
1058
1054
|
|
|
1059
|
-
**<input type="image">
|
|
1055
|
+
**<input type="image"> text alternative must be appropriate (manual review)**
|
|
1060
1056
|
|
|
1061
1057
|
manual · WCAG 1.1.1 (A) · confidence medium · default severity minor
|
|
1062
1058
|
|
|
1063
|
-
Flags <input type="image"> elements with non-empty alt
|
|
1059
|
+
Flags <input type="image"> elements with a non-empty text alternative (alt, aria-label, aria-labelledby or title) for human review of appropriateness.
|
|
1064
1060
|
|
|
1065
|
-
**Applies to.** Applies to <input type="image"> elements whose alt
|
|
1061
|
+
**Applies to.** Applies to <input type="image"> elements that get a non-empty text alternative from any source: aria-labelledby (resolving to text), aria-label, alt or title. An element whose alt is present but empty is left to input-image-alt-decorative, which asks about that case. The element must be included in the accessibility tree, and role="presentation"/"none" takes it out of scope unless it is focusable, which restores its role.
|
|
1066
1062
|
|
|
1067
|
-
**Expectation.** Human review is required to confirm that the provided text alternative is accurate and appropriate.
|
|
1063
|
+
**Expectation.** Human review is required to confirm that the provided text alternative is accurate and appropriate. Each occurrence lists every source present (data.details.sources), so the reviewer checks each one.
|
|
1068
1064
|
|
|
1069
1065
|
### `label-in-name`
|
|
1070
1066
|
|
|
@@ -1074,9 +1070,9 @@ automatic · WCAG 2.5.3 (A) · confidence high · default severity serious
|
|
|
1074
1070
|
|
|
1075
1071
|
Checks that when a control has a visible text label, the accessible name contains that visible label text (WCAG 2.5.3).
|
|
1076
1072
|
|
|
1077
|
-
**Applies to.** Applies to controls
|
|
1073
|
+
**Applies to.** Applies to controls named by aria-label or aria-labelledby, are visually rendered, and have visible label text this engine can extract deterministically, from an associated <label>, from the control's own rendered text, or from the elements aria-labelledby points at. The candidates are <button>, <a href>, <summary>, non-hidden form controls, and the button, link, checkbox, radio, switch, searchbox, tab, menuitem, menuitemcheckbox, menuitemradio, option, treeitem and gridcell roles, minus anything hidden or disabled. aria-hidden is not excluded: it changes nothing about what is rendered on screen, which is what this SC is about. An aria-label that is empty once trimmed, or an aria-labelledby whose ids point at nothing or only at elements with no text, names nothing: the accessible name then comes from the next source (the content, a <label>, title...), as for a control without them, so the control is out of scope.
|
|
1078
1074
|
|
|
1079
|
-
**Expectation.** The accessible name contains the visible label's words, adjacent and in order. The comparison is over words rather than characters: parenthesised text is dropped, case is folded, text is
|
|
1075
|
+
**Expectation.** The accessible name contains the visible label's words, adjacent and in order. The comparison is over words rather than characters: parenthesised text is dropped, case is folded, text is NFKC-normalised, and every character that is not a letter, digit or combining mark becomes a separator, so punctuation and spacing differences never decide the outcome. Accents are not folded: "Déposer" stays one word, and a name that drops an accent ("Deposer") does not contain it. Four shapes markup cannot settle are reported as cantTell instead of fail: a word hyphenated differently in the two places; a visible word the author may have abbreviated, marked by its trailing period; visible text rendered through a known icon font (the DOM text is real words, but nothing readable actually renders); and a whole visible label of exactly one character that doesn't even appear inside the accessible name, which per ACT 2ee8b8 may be "non-text content" (e.g. "X" meaning "close") rather than literal text.
|
|
1080
1076
|
|
|
1081
1077
|
### `label-title-only`
|
|
1082
1078
|
|
|
@@ -1204,26 +1200,25 @@ Checks that when two or more landmarks share the same role, each has a distinct
|
|
|
1204
1200
|
|
|
1205
1201
|
automatic · WCAG 1.4.1 (A) · confidence high · default severity serious
|
|
1206
1202
|
|
|
1207
|
-
Checks that a link inside a run of text is visually distinguishable from the surrounding text by underline,
|
|
1203
|
+
Checks that a link inside a run of text is visually distinguishable from the surrounding text by a non-color cue (underline, font-weight or style, border, background, icon), and asks about links distinguished only by a >=3:1 color difference, which also need a hover and focus cue.
|
|
1208
1204
|
|
|
1209
|
-
**Applies to.** Applies to
|
|
1205
|
+
**Applies to.** Applies to links (`<a href>` and elements with `role="link"`) whose immediate parent element also has at least one direct-child text node with non-whitespace content (i.e. the link sits inline within a run of plain text, not as a standalone item, e.g. not the sole content of a <li> nav item).
|
|
1210
1206
|
|
|
1211
1207
|
**Expectation.**
|
|
1212
1208
|
|
|
1213
1209
|
A link inside a text block must be visually distinguishable from the surrounding text by at least one non-color means:
|
|
1214
1210
|
|
|
1215
1211
|
- text-decoration: underline, OR
|
|
1216
|
-
- a different font-weight than the surrounding text, OR
|
|
1217
|
-
- a
|
|
1218
|
-
- a contrast ratio of at least 3:1 between the link's text color and the surrounding text's color (WCAG technique G183's threshold, sufficient contrast alone is an accepted alternative to underline).
|
|
1212
|
+
- a different font-weight or font-style than the surrounding text, OR
|
|
1213
|
+
- another visible mark on the link itself: a border, box-shadow or outline, a background color different from the surrounding one, a background image, an image or svg inside it, or ::before/::after content.
|
|
1219
1214
|
|
|
1220
|
-
|
|
1215
|
+
A link with none of these is distinguished by color alone. When its color contrasts with the surrounding text by at least 3:1, technique G183 is met only if hover and focus also bring a non-color cue, which a static scan cannot see, so the link is reported as cantTell. Below 3:1, with contrast confidently computable, color is demonstrably the only cue and the link fails.
|
|
1221
1216
|
|
|
1222
1217
|
### `link-name-present`
|
|
1223
1218
|
|
|
1224
1219
|
**Links have an accessible name**
|
|
1225
1220
|
|
|
1226
|
-
automatic · WCAG 4.1.2 (A) · confidence high · default severity serious
|
|
1221
|
+
automatic · WCAG 2.4.4, 4.1.2 (A) · confidence high · default severity serious
|
|
1227
1222
|
|
|
1228
1223
|
Checks that links expose a non-empty accessible name.
|
|
1229
1224
|
|
|
@@ -1237,7 +1232,7 @@ Checks that links expose a non-empty accessible name.
|
|
|
1237
1232
|
|
|
1238
1233
|
manual · WCAG 2.4.4 (A) · confidence medium · default severity minor
|
|
1239
1234
|
|
|
1240
|
-
Flags links whose full accessible name is a known non-descriptive phrase (e.g. "click here", "read more", "more") or a bare file-format name (e.g. "HTML", "PDF") with no adjacent context naming what it leads to, for manual review of whether the purpose is clear.
|
|
1235
|
+
Flags links whose full accessible name is a known non-descriptive phrase (e.g. "click here", "read more", "more") or a bare file-format name (e.g. "HTML", "PDF") with no adjacent context naming what it leads to, for manual review of whether the purpose is clear. English phrases are always recognized, and German, Spanish, French or Japanese ones when the link is in that language.
|
|
1241
1236
|
|
|
1242
1237
|
**Applies to.** Elements matching `a[href], area[href], [role="link"]` with a non-empty computed accessible name (programmatic first, then "name from content", same two-step resolution as `link-name-present`, same selector too). Links with no name at all are `link-name-present`'s concern, not this rule's.
|
|
1243
1238
|
|
|
@@ -1251,7 +1246,7 @@ automatic · WCAG 1.3.1 (A) · confidence high · default severity serious
|
|
|
1251
1246
|
|
|
1252
1247
|
Checks that <ul>/<ol> elements only have <li>, <script>, or <template> as direct children.
|
|
1253
1248
|
|
|
1254
|
-
**Applies to.** Applies to <ul>/<ol> elements that have at least one direct element child.
|
|
1249
|
+
**Applies to.** Applies to <ul>/<ol> elements that have at least one direct element child and whose role is list: no role attribute, role="list", or a role attribute naming no concrete ARIA role. A <ul>/<ol> given another role (listbox, menubar, tablist, none, ...) is not a list, so its children follow that role's rules instead.
|
|
1255
1250
|
|
|
1256
1251
|
**Expectation.** Every direct element child is <li>, <script>, or <template>. UNLESS it has an explicit `role` attribute, in which case the explicit role wins over the tag entirely: a child is valid iff that role is "listitem" (so `<li role="presentation">`/`<li role="menuitem">` are invalid despite the <li> tag, and conversely a non-<li> element explicitly given `role="listitem"` is valid). A wrapper <div> used for styling (no role at all) still breaks list semantics the same as before.
|
|
1257
1252
|
|
|
@@ -1273,11 +1268,11 @@ Checks that elements with role="listbox" expose a non-empty accessible name.
|
|
|
1273
1268
|
|
|
1274
1269
|
automatic · WCAG 1.3.1 (A) · confidence high · default severity serious
|
|
1275
1270
|
|
|
1276
|
-
Checks that <li> elements are contained by <ul>, <ol>, or an element with role="list".
|
|
1271
|
+
Checks that <li> elements are contained by <ul>, <ol>, <menu>, or an element with role="list".
|
|
1277
1272
|
|
|
1278
1273
|
**Applies to.** Applies to <li> elements that have a parent element.
|
|
1279
1274
|
|
|
1280
|
-
**Expectation.** The parent is <ul>/<ol> with no role override, or an element with an explicit role of "list", "presentation", or "none". An <li> used outside a real list container (e.g. as a generic flex/grid item under a <div>) is not exposed as a list item to assistive technologies.
|
|
1275
|
+
**Expectation.** The parent is <ul>/<ol>/<menu> with no role override (all three have the implicit role list), or an element with an explicit role of "list", "presentation", or "none". An <li> used outside a real list container (e.g. as a generic flex/grid item under a <div>) is not exposed as a list item to assistive technologies.
|
|
1281
1276
|
|
|
1282
1277
|
### `manual-review`
|
|
1283
1278
|
|
|
@@ -1317,11 +1312,11 @@ Checks that menu items (role="menuitem*", including checkbox/radio variants) exp
|
|
|
1317
1312
|
|
|
1318
1313
|
### `meta-refresh-no-exceptions`
|
|
1319
1314
|
|
|
1320
|
-
**Page must not use a meta refresh
|
|
1315
|
+
**Page must not use a timed meta refresh (AAA)**
|
|
1321
1316
|
|
|
1322
1317
|
automatic · WCAG 2.2.4, 3.2.5 (AAA) · confidence high · default severity moderate
|
|
1323
1318
|
|
|
1324
|
-
Checks that <meta http-equiv="refresh">
|
|
1319
|
+
Checks that <meta http-equiv="refresh"> does not set a positive delay, however long; an immediate redirect (delay 0) passes. This is the stricter AAA-level counterpart of the A-level check, which exempts delays over 20 hours.
|
|
1325
1320
|
|
|
1326
1321
|
**Applies to.** Applies to the first <meta http-equiv="refresh"> element, in document order, with a valid content attribute, per HTML's shared declarative refresh steps, a document only ever acts on its first valid meta refresh, so a later one (valid or not) is inert and out of scope.
|
|
1327
1322
|
|
|
@@ -1385,7 +1380,7 @@ Flags elements with an inline pointer-only event handler (onmouseover, onmouseou
|
|
|
1385
1380
|
|
|
1386
1381
|
**Applies to.** Elements carrying at least one inline pointer-only event-handler attribute (`onmouseover`, `onmouseout`, `onmousedown`, `onmouseup`, `ondblclick`, `onmousemove`, `onmouseenter`, `onmouseleave`) with a non-empty value, that are also eligible/reachable (not hidden/`aria-hidden`/`display:none`).
|
|
1387
1382
|
|
|
1388
|
-
**Expectation.** The element also carries at least one keyboard-reachable inline handler: `onkeydown`, `onkeyup`, `onkeypress` (the direct keyboard- event equivalents), or `onfocus`/`onblur` (the standard substitute for hover-triggered behavior: focus/blur are the keyboard- navigable analog to mouseover/mouseout, per WCAG technique G90). Otherwise the element's mouse-driven behavior (a hover tooltip, a custom dropdown, a drag interaction) has no way to be triggered by a keyboard-only user.
|
|
1383
|
+
**Expectation.** The element also carries at least one keyboard-reachable inline handler: `onkeydown`, `onkeyup`, `onkeypress` (the direct keyboard- event equivalents), or `onfocus`/`onblur` (the standard substitute for hover-triggered behavior: focus/blur are the keyboard- navigable analog to mouseover/mouseout, per WCAG technique G90). A handler is reachable only if keyboard events can reach it: `onfocus`/`onblur` when the element itself can take focus, and a key handler when the element or one of its descendants can (key events bubble, focus events do not). Otherwise the element's mouse-driven behavior (a hover tooltip, a custom dropdown, a drag interaction) has no way to be triggered by a keyboard-only user, and it is flagged with a reason saying whether the keyboard handlers are missing or cannot run.
|
|
1389
1384
|
|
|
1390
1385
|
### `nested-interactive-controls-absent`
|
|
1391
1386
|
|
|
@@ -1405,9 +1400,9 @@ Checks that an interactive control (link, button, form control, or ARIA widget r
|
|
|
1405
1400
|
|
|
1406
1401
|
manual · WCAG 1.4.2 (A) · confidence low · default severity moderate
|
|
1407
1402
|
|
|
1408
|
-
Flags <audio>/<video> elements that autoplay unmuted with no native controls attribute, for manual review against the 3-second exemption in WCAG 1.4.2.
|
|
1403
|
+
Flags <audio>/<video> elements that autoplay unmuted with no native controls attribute, and <embed>, <object> or <bgsound> elements that may play sound, for manual review against the 3-second exemption in WCAG 1.4.2.
|
|
1409
1404
|
|
|
1410
|
-
**Applies to.** Any <audio autoplay> or <video autoplay> element that is not `muted`.
|
|
1405
|
+
**Applies to.** Any <audio autoplay> or <video autoplay> element that is not `muted`. Also any <bgsound>, and any <embed> or <object> that loads sound or video, or a plugin (Flash) that may play it: its `type` is audio/*, video/* or a plugin type, or its `src`/`data` ends in a sound or video file extension. An <embed> or <object> with `autostart` or `autoplay` set to false (attribute or <param>) is left out.
|
|
1411
1406
|
|
|
1412
1407
|
**Expectation.** SC 1.4.2 only applies when audio plays automatically for MORE than 3 seconds; clip duration is not knowable from static markup (jsdom does not decode media), so this rule cannot determine whether the SC even applies to a given element. It is authored as `type: 'manual'` (cantTell-capped, never fail) on purpose rather than guessing: an autoplaying unmuted element with no `controls` attribute (the native, statically-verifiable mechanism to pause/stop or adjust volume) is flagged for human review rather than treated as a deterministic violation.
|
|
1413
1408
|
|
|
@@ -1455,13 +1450,13 @@ Checks that elements with role="option" expose a non-empty accessible name.
|
|
|
1455
1450
|
|
|
1456
1451
|
### `p-as-heading`
|
|
1457
1452
|
|
|
1458
|
-
**
|
|
1453
|
+
**Text styled to look like a heading should probably be a real heading**
|
|
1459
1454
|
|
|
1460
1455
|
manual · WCAG 1.3.1 (A) · confidence low · default severity minor
|
|
1461
1456
|
|
|
1462
|
-
Flags short <p> elements whose
|
|
1457
|
+
Flags short <p> and <div> elements whose text is all bold and rendered at >=18px, for manual review of whether a real heading element should be used instead.
|
|
1463
1458
|
|
|
1464
|
-
**Applies to.** `<p>` elements with short (<=120 char), non-empty trimmed text
|
|
1459
|
+
**Applies to.** `<p>` elements, and `<div>` elements that hold only text and inline markup, with short (<=120 char), non-empty trimmed text in which every piece of text is bold (computed `font-weight` >= 700, however it got there: on the element itself, a `<strong>`/`<b>` or a styled `<span>`) and rendered at >=18px.
|
|
1465
1460
|
|
|
1466
1461
|
**Expectation.** Text styled to visually read as a heading (bold, larger-than-body size, short) should be marked up with a real heading element (`<h1>`-`<h6>` or `role="heading"`) so its structural role is programmatically determinable, the same 1.3.1 concern as any other "structure conveyed through presentation only" issue.
|
|
1467
1462
|
|
|
@@ -1485,7 +1480,7 @@ manual · WCAG 2.4.2 (A) · confidence medium · default severity minor
|
|
|
1485
1480
|
|
|
1486
1481
|
Identifies page title patterns that may indicate low descriptiveness, such as generic, duplicated, or overly templated titles. This rule provides review signals and does not fail automatically.
|
|
1487
1482
|
|
|
1488
|
-
**Applies to.** Applies to a run over a whole document whose <title> resolves to non-empty text; a missing or empty title is page-title-present's failure, not a pattern to review. A run narrowed by contextSelector or by engineOptions.fragment is notApplicable, as is a title matching none of the patterns below.
|
|
1483
|
+
**Applies to.** Applies to a run over a whole document whose <title> resolves to non-empty text. The title element is the first HTML <title> anywhere in the document, as for document.title, so one the parser left in <body> counts; a missing or empty title is page-title-present's failure, not a pattern to review. A run narrowed by contextSelector or by engineOptions.fragment is notApplicable, as is a title matching none of the patterns below.
|
|
1489
1484
|
|
|
1490
1485
|
**Expectation.** The title carries none of the conservative low-descriptiveness signals: one of the generic titles home, homepage, welcome, untitled, page or document; fewer than eight characters; or a template shape pairing a generic token with a brand, such as "Home | Brand". When the crawl.pageTitles probe supplies at least ten pages, cross-page signals are used instead: one title repeated across distinct URLs, or a prefix or suffix of twelve characters or more shared across the set. Every signal is reported as cantTell: whether a title describes its page is a judgment, so the rule never fails on a pattern alone.
|
|
1491
1486
|
|
|
@@ -1499,7 +1494,7 @@ Checks that the page includes a non-empty <title> element.
|
|
|
1499
1494
|
|
|
1500
1495
|
**Applies to.** Applies to a run over a whole document. A run narrowed by contextSelector, or by engineOptions.fragment, is notApplicable: whether the page has a title is not a property any subtree can answer.
|
|
1501
1496
|
|
|
1502
|
-
**Expectation.** The document has a <title> element, and document.title with whitespace collapsed is non-empty. The element is looked for anywhere in the document, not only inside <head>: a <title> the parser leaves outside <head> is still the document title in every browser. Whether that title describes the page is page-title-patterns' question.
|
|
1497
|
+
**Expectation.** The document has a <title> element, and document.title with whitespace collapsed is non-empty. The element is looked for anywhere in the document, not only inside <head>: a <title> the parser leaves outside <head> is still the document title in every browser. Only an HTML-namespace <title> counts; the <title> of an inline <svg> names the graphic, so a page whose only <title> is inside an <svg> is missing its title element. Whether that title describes the page is page-title-patterns' question.
|
|
1503
1498
|
|
|
1504
1499
|
### `password-paste-enabled`
|
|
1505
1500
|
|
|
@@ -1547,7 +1542,7 @@ Checks that elements with role="progressbar" expose a non-empty accessible name.
|
|
|
1547
1542
|
|
|
1548
1543
|
**Applies to.** Applies to elements carrying role="progressbar" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope.
|
|
1549
1544
|
|
|
1550
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="progressbar" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom progressbar widget is not reliably exposed as its name.
|
|
1545
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="progressbar" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom progressbar widget is not reliably exposed as its name. On a labelable element (<progress role="progressbar">) an associated <label> counts as well.
|
|
1551
1546
|
|
|
1552
1547
|
### `region`
|
|
1553
1548
|
|
|
@@ -1569,7 +1564,7 @@ automatic · WCAG 1.1.1 (A) · confidence high · default severity serious
|
|
|
1569
1564
|
|
|
1570
1565
|
Checks that elements with role="img", "graphics-symbol" or "graphics-document" provide an accessible text alternative using aria-label, aria-labelledby, a title attribute, or (for SVG elements) a first-child <title>.
|
|
1571
1566
|
|
|
1572
|
-
**Applies to.** Applies to elements with role="img", role="graphics-symbol" or role="graphics-document" that are included in the accessibility tree (ACT 23a2a8's "programmatically hidden" exemption: display:none/visibility:hidden/aria-hidden="true" on the element or an ancestor, with no carve-out for focusable or IDREF-referenced elements, aria-hidden-focus and duplicate-id-aria own those separately). Per ACT 7d6734, this reaches any element carrying one of these roles, not only the <svg> root, e.g. a <circle role="graphics-symbol"> nested inside a plain <svg>.
|
|
1567
|
+
**Applies to.** Applies to elements with role="img", role="graphics-symbol" or role="graphics-document" that are included in the accessibility tree (ACT 23a2a8's "programmatically hidden" exemption: display:none/visibility:hidden/aria-hidden="true" on the element or an ancestor, with no carve-out for focusable or IDREF-referenced elements, aria-hidden-focus and duplicate-id-aria own those separately). Per ACT 7d6734, this reaches any element carrying one of these roles, not only the <svg> root, e.g. a <circle role="graphics-symbol"> nested inside a plain <svg>. Every <svg> element itself is left to svg-text-alternative-present's own (already ACT-clean) title/aria-name handling, so an unnamed <svg role="img"> is reported once, there; the <img> tag is excluded here since it has its own dedicated rule.
|
|
1573
1568
|
|
|
1574
1569
|
**Expectation.**
|
|
1575
1570
|
|
|
@@ -1614,19 +1609,19 @@ Checks that elements with role="searchbox" expose a non-empty accessible name.
|
|
|
1614
1609
|
|
|
1615
1610
|
**Applies to.** Applies to elements carrying role="searchbox" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope.
|
|
1616
1611
|
|
|
1617
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="searchbox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom searchbox widget is not reliably exposed as its name. On a labelable element (<input role="searchbox">) an associated <label> counts as well.
|
|
1612
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="searchbox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom searchbox widget is not reliably exposed as its name. On a labelable element (<input role="searchbox">) an associated <label> counts as well. On a text-like <input> or a <textarea>, the placeholder counts last (HTML-AAM's final name source): a placeholder-only label is a 3.3.2 question, not a missing name.
|
|
1618
1613
|
|
|
1619
1614
|
### `server-side-image-map-absent`
|
|
1620
1615
|
|
|
1621
|
-
**
|
|
1616
|
+
**Server-side image maps must have a keyboard-operable alternative**
|
|
1622
1617
|
|
|
1623
1618
|
automatic · WCAG 2.1.1 (A) · confidence high · default severity serious
|
|
1624
1619
|
|
|
1625
|
-
|
|
1620
|
+
Asks, for each <img ismap> inside a link, whether the page offers the same destinations as links a keyboard can reach, since a server-side image map has no keyboard-operable regions of its own.
|
|
1626
1621
|
|
|
1627
|
-
**Applies to.** Applies to <img>
|
|
1622
|
+
**Applies to.** Applies to any scan scope. An <img ismap> inside an <a href> is a server-side image map: the browser sends the click coordinates to the link's URL, which has no keyboard-operable equivalent and exposes no individual regions to assistive technology.
|
|
1628
1623
|
|
|
1629
|
-
**Expectation.**
|
|
1624
|
+
**Expectation.** Each server-side image map is reported as cantTell: 2.1.1 is met when the same destinations are also offered as links a keyboard can reach, which the rule cannot verify. Client-side image maps (<map>/<area>) are not flagged. A scope with no <img ismap> passes. One whose only <img ismap> elements are outside a link is notApplicable: ismap does nothing there, so there is no server-side image map (the misplaced attribute is invalid HTML, a matter for the validator).
|
|
1630
1625
|
|
|
1631
1626
|
### `skip-link`
|
|
1632
1627
|
|
|
@@ -1636,7 +1631,14 @@ manual · no formal WCAG SC mapping · confidence medium · default severity min
|
|
|
1636
1631
|
|
|
1637
1632
|
Checks that a "skip to ..." link's href fragment resolves to a real, currently usable element in the document.
|
|
1638
1633
|
|
|
1639
|
-
**Applies to.**
|
|
1634
|
+
**Applies to.**
|
|
1635
|
+
|
|
1636
|
+
Applies to <a href="#fragment"> elements that are skip links by one of two signs:
|
|
1637
|
+
|
|
1638
|
+
- the accessible name follows a common skip-link wording in one of the shipped locales: "skip" or "jump to" (English); "aller au contenu", "passer au contenu", "accéder au contenu", "accès direct", "évitement" (French); "springen", "überspringen", "direkt zum", "zum Inhalt" (German); "saltar", "ir al contenido" (Spanish); "スキップ", "本文へ" (Japanese). "jump to" sits beside "skip" because real skip links use both conventions (e.g. a "Jump to section" link);
|
|
1639
|
+
- or it is the first link in the document, and it comes before the `main` element (or `[role="main"]`): the usual place of a skip link whatever its wording.
|
|
1640
|
+
|
|
1641
|
+
Other same-page anchor links are not skip links and are left alone.
|
|
1640
1642
|
|
|
1641
1643
|
**Expectation.** The link's fragment resolves to a real element in the document (via a matching id, or a legacy <a name="...">), and that target is currently usable (not hidden from the accessibility tree; and, when browser geometry is available, not zero-area/no-rects). A skip link whose target is missing or effectively unusable does not provide a reliable bypass destination.
|
|
1642
1644
|
|
|
@@ -1650,7 +1652,7 @@ Checks that sliders (input[type="range"] and role="slider") expose a non-empty a
|
|
|
1650
1652
|
|
|
1651
1653
|
**Applies to.** Applies to elements carrying role="slider" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope. A native <input type="range"> without the role belongs to form-control-programmatic-label-present.
|
|
1652
1654
|
|
|
1653
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="slider" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom slider widget is not reliably exposed as its name. On a labelable element (<input role="slider">) an associated <label> counts as well.
|
|
1655
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="slider" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom slider widget is not reliably exposed as its name. On a labelable element (<input role="slider">) an associated <label> counts as well. On a text-like <input> or a <textarea>, the placeholder counts last (HTML-AAM's final name source): a placeholder-only label is a 3.3.2 question, not a missing name.
|
|
1654
1656
|
|
|
1655
1657
|
### `spinbutton-name-present`
|
|
1656
1658
|
|
|
@@ -1662,7 +1664,7 @@ Checks that elements with role="spinbutton" expose a non-empty accessible name.
|
|
|
1662
1664
|
|
|
1663
1665
|
**Applies to.** Applies to elements carrying role="spinbutton" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope.
|
|
1664
1666
|
|
|
1665
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="spinbutton" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom spinbutton widget is not reliably exposed as its name. On a labelable element (<input role="spinbutton">) an associated <label> counts as well.
|
|
1667
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="spinbutton" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom spinbutton widget is not reliably exposed as its name. On a labelable element (<input role="spinbutton">) an associated <label> counts as well. On a text-like <input> or a <textarea>, the placeholder counts last (HTML-AAM's final name source): a placeholder-only label is a 3.3.2 question, not a missing name.
|
|
1666
1668
|
|
|
1667
1669
|
### `summary-name-present`
|
|
1668
1670
|
|
|
@@ -1778,7 +1780,7 @@ manual · WCAG 1.3.1 (A) · confidence low · default severity minor
|
|
|
1778
1780
|
|
|
1779
1781
|
Flags tables with no <caption> whose first row has a single non-empty cell while other rows have multiple cells, for manual review of whether that cell is acting as a fake caption.
|
|
1780
1782
|
|
|
1781
|
-
**Applies to.** `<table>` elements with no `<caption>` child, at least two rows, and a first row containing exactly one non-empty-text cell while at least one other row has more than one cell.
|
|
1783
|
+
**Applies to.** `<table>` elements with no `<caption>` child, at least two rows, and a first row containing exactly one non-empty-text cell while at least one other row has more than one cell. Left out: a table whose role (first token) is anything but table, grid or treegrid, such as a layout table with role="presentation", which needs no caption; and a table already named by a non-empty aria-label, an aria-labelledby that resolves to text, or a non-empty title, which WCAG accepts as the table's title.
|
|
1782
1784
|
|
|
1783
1785
|
**Expectation.** A single lone cell in the first row, sitting above rows that clearly have multiple columns, strongly suggests the author is using it as a visual caption/title rather than as a real table cell. Structure conveyed only through this positional convention is not programmatically associated with the table the way a real `<caption>` element is (1.3.1).
|
|
1784
1786
|
|
|
@@ -1844,15 +1846,36 @@ automatic · WCAG 1.3.1 (A) · confidence high · default severity serious
|
|
|
1844
1846
|
|
|
1845
1847
|
Checks that every <td> in a large, simple (no colspan/rowspan) table has an associated header, via a headers attribute, an implicit column <th> above it, or an implicit row <th> to its left.
|
|
1846
1848
|
|
|
1847
|
-
**Applies to.** `<table>` elements with at least 4 rows and at least 4 columns (a "large" table, where implicit row/column header association is useful; small tables are usually self-evident), and with NO `colspan`/`rowspan` anywhere in the table.
|
|
1849
|
+
**Applies to.** `<table>` elements with at least 4 rows and at least 4 columns (a "large" table, where implicit row/column header association is useful; small tables are usually self-evident), and with NO `colspan`/`rowspan` anywhere in the table. A table whose role (first token) is anything but table, grid or treegrid, such as a layout table with role="presentation", is left out: it has no data cells.
|
|
1848
1850
|
|
|
1849
1851
|
**Expectation.**
|
|
1850
1852
|
|
|
1851
|
-
Every `<td>` has an associated header, via one of:
|
|
1853
|
+
Every non-empty `<td>` has an associated header, via one of:
|
|
1852
1854
|
|
|
1853
1855
|
- a non-empty `headers` attribute (trusted here; whether it resolves to real `<th>` ids is `table-headers-attr-valid`'s concern, not this rule's), OR
|
|
1854
|
-
- an implicit column header:
|
|
1855
|
-
- an implicit row header:
|
|
1856
|
+
- an implicit column header: a header cell in the same column, in an earlier row, OR
|
|
1857
|
+
- an implicit row header: a header cell earlier in the same row.
|
|
1858
|
+
|
|
1859
|
+
A header cell is a `<th>` with no other role, or any cell with role="columnheader" or role="rowheader" (such a `<td>` is a header, not a data cell). A `<td>` with no text and no content that could carry a name (an image, a control, an element with an ARIA label) holds no data, so it needs no header; the empty corner cell above row headers is the usual case.
|
|
1860
|
+
|
|
1861
|
+
### `text-spacing-content-loss`
|
|
1862
|
+
|
|
1863
|
+
**Text stays readable when the user increases text spacing**
|
|
1864
|
+
|
|
1865
|
+
automatic · WCAG 1.4.12 (AA) · confidence medium · default severity serious
|
|
1866
|
+
|
|
1867
|
+
Applies the WCAG 1.4.12 text spacing in the browser and checks that no text is cut off or made to overlap, and asks about style sheet rules that force spacing with !important.
|
|
1868
|
+
|
|
1869
|
+
**Applies to.** Applies to a page with visible text. The loss of content needs a layout (a browser): without one, only the style sheets are read.
|
|
1870
|
+
|
|
1871
|
+
**Expectation.**
|
|
1872
|
+
|
|
1873
|
+
WCAG 1.4.12: with line height at 1.5 times the font size, spacing after paragraphs at 2 times, letter spacing at 0.12 times and word spacing at 0.16 times, no content or functionality is lost.
|
|
1874
|
+
|
|
1875
|
+
- In a browser, the spacing is applied as a style sheet that wins over the page's own (inline `!important` aside, which avoid-inline-spacing reports), and each line of text is measured before and after against the ancestors that clip it (`overflow: hidden` or `clip`). A line that was inside and ends at least half outside (half its height, or half an em across) fails: the container cuts that text off (TEXT_CLIPPED). A line pushed out by less is asked about (TEXT_CLIPPED_PARTLY), and so is text that comes to overlap other text it did not overlap before (TEXT_OVERLAPS).
|
|
1876
|
+
- In any environment, a style sheet rule that sets line-height, letter-spacing or word-spacing below those values with `!important` is asked about (STYLESHEET_IMPORTANT): a tool that adds its own style sheet to the page cannot override it, though a user style sheet can.
|
|
1877
|
+
|
|
1878
|
+
Without a layout and with no such rule, the rule is notApplicable, with `data.reason: 'noLayout'`.
|
|
1856
1879
|
|
|
1857
1880
|
### `textbox-name-present`
|
|
1858
1881
|
|
|
@@ -1864,7 +1887,7 @@ Checks that elements with role="textbox" expose a non-empty accessible name.
|
|
|
1864
1887
|
|
|
1865
1888
|
**Applies to.** Applies to elements carrying role="textbox" (the attribute must name that role alone, not a fallback list) that are included in the accessibility tree. An element with the matching implicit role but no role attribute is out of scope.
|
|
1866
1889
|
|
|
1867
|
-
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="textbox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom textbox widget is not reliably exposed as its name. On a labelable element (<input role="textbox">) an associated <label> counts as well.
|
|
1890
|
+
**Expectation.** The element has a non-empty accessible name from aria-label, from an aria-labelledby that resolves to non-empty text, or from title. role="textbox" is name-from-author-only, so subtree text is never accepted: text sitting inside a custom textbox widget is not reliably exposed as its name. On a labelable element (<input role="textbox">) an associated <label> counts as well. On a text-like <input> or a <textarea>, the placeholder counts last (HTML-AAM's final name source): a placeholder-only label is a 3.3.2 question, not a missing name.
|
|
1868
1891
|
|
|
1869
1892
|
### `tooltip-name-present`
|
|
1870
1893
|
|
|
@@ -1906,7 +1929,7 @@ Applies to any element other than the root <html> with a non-empty lang at
|
|
|
1906
1929
|
- A non-empty alt attribute on img/area/input[type=image] counts as governed text, the same as a text node.
|
|
1907
1930
|
- Text (or alt) that CSS keeps out of the render tree (display:none, the hidden attribute, ...) does not count. aria-hidden and offscreen positioning do NOT exempt text, per ACT's own failed examples for both, only actual non-rendering does.
|
|
1908
1931
|
|
|
1909
|
-
**Expectation.** The lang value
|
|
1932
|
+
**Expectation.** The primary language subtag of the lang value (the part before the first hyphen) is a registered language subtag, as ACT de46e4 requires. WCAG 3.1.2 (Language of Parts) requires that when a passage's language differs from the page's default, it is identified programmatically. A tag whose primary subtag is unknown fails to identify a real language at all; a malformed later subtag (lang="en-US_x") still identifies English and passes here, since it is a markup validity error rather than a missing language.
|
|
1910
1933
|
|
|
1911
1934
|
### `video-caption`
|
|
1912
1935
|
|
|
@@ -1914,11 +1937,11 @@ Applies to any element other than the root <html> with a non-empty lang at
|
|
|
1914
1937
|
|
|
1915
1938
|
manual · WCAG 1.2.2 (A) · confidence low · default severity moderate
|
|
1916
1939
|
|
|
1917
|
-
Flags <video> elements with no <track kind="captions"
|
|
1940
|
+
Flags <video> elements with no <track kind="captions"> child, for manual review of whether the video has an audio track that needs captions; a subtitles track alone may be a translation only.
|
|
1918
1941
|
|
|
1919
1942
|
**Applies to.** Any <video> element in the composed DOM.
|
|
1920
1943
|
|
|
1921
|
-
**Expectation.** SC 1.2.2 requires captions for prerecorded synchronized media, but only when the video actually has an audio track that conveys information (a silent/decorative video needs none), which cannot be verified from static markup alone (jsdom does not decode media). This rule is therefore `type: 'manual'` (cantTell-capped, never fail), matching the precedent set by `media-alternative-transcript-evidence` for the same class of "normatively mapped but not statically verifiable" gap. A <video> with a `<track kind="captions">`
|
|
1944
|
+
**Expectation.** SC 1.2.2 requires captions for prerecorded synchronized media, but only when the video actually has an audio track that conveys information (a silent/decorative video needs none), which cannot be verified from static markup alone (jsdom does not decode media). This rule is therefore `type: 'manual'` (cantTell-capped, never fail), matching the precedent set by `media-alternative-transcript-evidence` for the same class of "normatively mapped but not statically verifiable" gap. A <video> with a `<track kind="captions">` whose `src` is non-empty is not flagged; everything else is flagged for human review. A video whose only text tracks are subtitles (`kind="subtitles"`, or no `kind`, which HTML treats as subtitles) gets its own question: subtitles may be a translation of the dialogue only, without the speaker and sound information captions carry.
|
|
1922
1945
|
|
|
1923
1946
|
### `video-poster-text-alternative-present`
|
|
1924
1947
|
|