$npx -y skills add mgifford/accessibility-skills --skill axe-rulesLoad this skill when configuring axe-core scans, reviewing automated accessibility test results, or writing tests that use @axe-core/playwright, @axe-core/react, or similar integrations. Provides a quick reference to axe 4.x rule IDs, their WCAG mapping, and default severity leve
| 1 | # Axe-Core Rules Reference Skill |
| 2 | |
| 3 | > **Canonical source**: `examples/AXE_RULES_REFERENCE.md` and `examples/AXE_RULES_COVERAGE.md` in `mgifford/ACCESSIBILITY.md` |
| 4 | > This skill is derived from those files. When in doubt, the example is authoritative. |
| 5 | > **Note:** the canonical files are organized around a specific test-fixture scanner |
| 6 | > project (numbered test pages). This skill re-presents the same rule set and |
| 7 | > severities as a general-purpose reference, independent of any particular fixture. |
| 8 | |
| 9 | Apply these rules when writing, reviewing, or debugging axe-core scans. |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## Core Principle |
| 14 | |
| 15 | Axe-core catches ~30–40% of WCAG issues automatically. It is the baseline, |
| 16 | not the ceiling. Always pair automated scanning with manual keyboard and screen |
| 17 | reader testing. |
| 18 | |
| 19 | **Key tags to include in scans:** |
| 20 | |
| 21 | ```typescript |
| 22 | .withTags(['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa']) |
| 23 | ``` |
| 24 | |
| 25 | Axe-core 4.11 includes 100+ automated checks across these categories: WCAG 2.0 |
| 26 | A/AA (68 rules), WCAG 2.1 A/AA (26 rules), WCAG 2.2 A/AA (1 rule, disabled by |
| 27 | default), Best Practices (30+ rules), WCAG AAA (3 rules, disabled by default), |
| 28 | Experimental (9 rules, disabled by default), and Deprecated (7 rules, disabled |
| 29 | by default). |
| 30 | |
| 31 | --- |
| 32 | |
| 33 | ## Severity Scale (axe-core) |
| 34 | |
| 35 | | axe severity | Meaning | |
| 36 | |---|---| |
| 37 | | **critical** | Blocks access for one or more disability groups | |
| 38 | | **serious** | Significantly impairs access | |
| 39 | | **moderate** | Creates friction; workaround exists | |
| 40 | | **minor** | Best-practice gap; marginal impact | |
| 41 | |
| 42 | --- |
| 43 | |
| 44 | ## Critical Rules — must never appear in production |
| 45 | |
| 46 | | Rule ID | Category | Description | |
| 47 | |---|---|---| |
| 48 | | `image-alt` | Text alternatives | `<img>` missing `alt` attribute | |
| 49 | | `area-alt` | Text alternatives | Image map `<area>` missing alt text | |
| 50 | | `input-image-alt` | Text alternatives | `<input type="image">` missing alt | |
| 51 | | `video-caption` | Text alternatives | `<video>` without captions | |
| 52 | | `aria-allowed-attr` | ARIA | Element has unsupported ARIA attributes for its role | |
| 53 | | `aria-hidden-body` | ARIA | `aria-hidden` applied to `<body>` | |
| 54 | | `aria-required-attr` | ARIA | Required ARIA attribute missing | |
| 55 | | `aria-required-children` | ARIA | Required child ARIA roles missing | |
| 56 | | `aria-required-parent` | ARIA | Required parent ARIA role missing | |
| 57 | | `aria-roles` | ARIA | Invalid ARIA role value | |
| 58 | | `aria-valid-attr` | ARIA | Invalid ARIA attribute name | |
| 59 | | `aria-valid-attr-value` | ARIA | ARIA attribute has invalid value | |
| 60 | | `label` | Forms | Form input without associated `<label>` | |
| 61 | | `select-name` | Forms | `<select>` without accessible name | |
| 62 | | `button-name` | Buttons/Links | Button without discernible text | |
| 63 | | `input-button-name` | Buttons/Links | `<input type="button">` without text | |
| 64 | | `duplicate-id-aria` | Structure | Duplicate `id` values referenced by ARIA | |
| 65 | | `meta-refresh` | Meta | `<meta http-equiv="refresh">` causes timed redirect | |
| 66 | |
| 67 | --- |
| 68 | |
| 69 | ## Serious Rules — fix before release |
| 70 | |
| 71 | | Rule ID | Category | Description | |
| 72 | |---|---|---| |
| 73 | | `object-alt` | Text alternatives | `<object>` without accessible text | |
| 74 | | `svg-img-alt` | Text alternatives | SVG with `role="img"` and no accessible name | |
| 75 | | `role-img-alt` | Text alternatives | Element with `role="img"` lacks alt text | |
| 76 | | `aria-braille-equivalent` | ARIA | Braille label without non-braille equivalent | |
| 77 | | `aria-command-name` | ARIA | Button, link, or menu item without accessible name | |
| 78 | | `aria-conditional-attr` | ARIA | ARIA attribute used contrary to role spec | |
| 79 | | `aria-hidden-focus` | ARIA | `aria-hidden` element contains focusable content | |
| 80 | | `aria-input-field-name` | ARIA | ARIA input field without accessible name | |
| 81 | | `aria-meter-name` | ARIA | ARIA `meter` element without accessible name | |
| 82 | | `aria-progressbar-name` | ARIA | ARIA `progressbar` element without accessible name | |
| 83 | | `aria-prohibited-attr` | ARIA | Prohibited ARIA attribute used | |
| 84 | | `aria-toggle-field-name` | ARIA | ARIA toggle field without accessible name | |
| 85 | | `aria-tooltip-name` | ARIA | ARIA tooltip without accessible name | |
| 86 | | `aria-dialog-name` | ARIA | Dialog without accessible name | |
| 87 | | `aria-treeitem-name` | ARIA | Tree item without accessible name | |
| 88 | | `color-contrast` | Color | Text contrast below 4.5:1 (normal) or 3:1 (large) | |
| 89 | | `frame-title` | Frames | `<iframe>` without accessible name | |
| 90 | | `frame-title-unique` | Frames | Frame titles are not unique | |
| 91 | | `frame-focusable-content` | Frames | Frame with focusable content is `tabindex="-1"` | |
| 92 | | `html-has-lang` | Language | `<html>` missing `lang` attribute | |
| 93 | | `html-lang-valid` | Language | `lang` attribute has invalid BCP 47 value | |
| 94 | | `valid-lang` | Language | Inline `lang` value is invalid | |
| 95 | | `document-title` | Language | `<title>` |