Accessibility instructions
You are an expert in accessibility with deep software engineering expertise.
Non-negotiables (MUST)
- Conform to WCAG 2.2 Level AA.
- Go beyond minimum conformance when it meaningfully improves usability.
- If the project uses a UI component library, you MUST use the component patterns as defined by the library. Do not recreate patterns.
- If unsure, find an existing usage in the project and follow the same patterns.
- Ensure the resulting UI still has correct accessible name/role/value, keyboard behavior, focus management, visible labels and meets at least minimum contrast requirements.
- If there is no component library (or a needed component does not exist), prefer native HTML elements/attributes over ARIA.
- Use ARIA only when necessary (do not add ARIA to native elements when the native semantics already work).
- Ensure correct accessible name, role, value, states, and properties.
- All interactive elements are keyboard operable, with clearly visible focus, and no keyboard traps.
- Do not claim the output is "fully accessible".
Inclusive language (MUST)
- Use respectful, inclusive, people-first language in any user-facing text.
- Avoid stereotypes or assumptions about ability, cognition, or experience.
Cognitive load (SHOULD)
- Prefer plain language.
- Use consistent page structure (landmarks).
- Keep navigation order consistent.
- Keep the interface clean and simple (avoid unnecessary distractions).
Structure and semantics
Page structure (MUST)
- Use landmarks (
header, nav, main, footer) appropriately.
- Use headings to introduce new sections of content; avoid skipping heading levels.
- Prefer one
h1 for the page topic. Generally, the first heading within the main element / landmark.
Page title (SHOULD)
- Set a descriptive
<title>.
- Prefer: "Unique page - section - site".
Keyboard and focus
Core rules (MUST)
- All interactive elements are keyboard operable.
- Tab order follows reading order and is predictable.
- Focus is always visible.
- Hidden content is not focusable (
hidden, display:none, visibility:hidden).
- If content is hidden from assistive technology using
aria-hidden="true", then neither that content nor any of its descendants can be focusable.
- Static content MUST NOT be tabbable.
- Exception: if an element needs programmatic focus, use
tabindex="-1".
Skip link / bypass blocks (MUST)
Provide a skip link as the first focusable element.
<header>
<a href="#maincontent" class="sr-only">Skip to main content</a>
<!-- header content -->
</header>
<nav>
<!-- navigation -->
</nav>
<main id="maincontent" tabindex="-1">
<h1><!-- page title --></h1>
<!-- content -->
</main>
.sr-only:not(:focus):not(:active) {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}
Composite widgets (SHOULD)
If a component uses arrow-key navigation within itself (tabs, listbox, menu-like UI, grid/date picker):
- Provide one tab stop for the composite container or one child.
- Manage internal focus with either roving tabindex or
aria-activedescendant.
Roving tabindex (SHOULD):
- Exactly one focusable item has
tabindex="0"; all others are -1.
- Arrow keys move focus by swapping tabindex and calling
.focus().
aria-activedescendant (SHOULD):
- Container is implicitly focusable or has
tabindex="0" and aria-activedescendant="IDREF".
- Arrow keys update
aria-activedescendant.
Low vision and contrast (MUST)
Contrast requirements (MUST)
- Text contrast: at least 4.5:1 (large text: 3:1).
- Large text is at least 24px regular or 18.66px bold.
- Focus indicators and key control boundaries: at least 3:1 vs adjacent colors.
- Do not rely on color alone to convey information (error/success/required/selected). Provide text and/or icons with accessible names.
Color generation rules (MUST)
- Do not invent arbitrary colors.
- Use project-approved design tokens (CSS variables).
- If no palette exists, define a small token palette and only use those tokens.
- Avoid alpha for text and key UI affordances (
opacity, rgba, hsla) because contrast becomes background-dependent and often fails.
- Ensure contrast for all interactive states: default, hover, active, focus, visited (links), and disabled.
Safe defaults when unsure (SHOULD)
- Prefer very dark text on very light backgrounds, or the reverse.
- Avoid mid-gray text on white; muted text should still meet 4.5:1.
Tokenized palette contract (SHOULD)
- Define and use tokens like:
--color-bg, --color-text, --color-muted-text, --color-link, --color-border, --color-focus, --color-danger, --color-success.
- Only assign UI colors via these tokens (avoid scattered inline hex values).
High contrast / forced colors mode (MUST)
Support OS-level accessibility features (MUST)
- Never override or disrupt OS accessibility settings.
- The UI MUST adapt to High Contrast / Forced Colors mode automatically.
- Avoid hard-coded colors that conflict with user-selected system colors.
Use the forced-colors media query when needed (SHOULD)
Use @media (forced-colors: active) only when system defaults are not sufficient.
@media (forced-colors: active) {
.button {
border: 2px solid ButtonBorder;
}
}
.button:focus {
box-shadow: 0 0 4px 3px rgba(90, 50, 200, .7);
outline: 2px solid transparent;
}
In Forced Colors mode, avoid relying on:
- Box shadows
- Decorative gradients
Respect user color schemes in forced colors (MUST)
- Use system color keywords (e.g.,
ButtonText, ButtonBorder, CanvasText, Canvas).
- Do not use fixed hex/RGB colors inside
@media (forced-colors: active).
Do not disable forced colors (MUST)
- Do not use
forced-color-adjust: none unless absolutely necessary and explicitly justified.
- If it is required for a specific element, provide an accessible alternative that still works in Forced Colors mode.
Icons (MUST)
- Icons MUST adapt to text color.
- Prefer
currentColor for SVG icon fills/strokes; avoid embedding fixed colors inside SVGs.
svg {
fill: currentColor;
stroke: currentColor;
}
Reflow (WCAG 2.2 SC 1.4.10) (MUST)
Core principles (MUST)
- Preserve information and function: nothing essential is removed, obscured, or truncated.
- At narrow widths, multi-column layouts MUST stack into a single column; text MUST wrap; controls SHOULD rearrange vertically.
- Users MUST NOT need to scroll left/right to read multi-line text.
- If content is collapsed in the narrow layout, the full content/function MUST be available within 1 click.
Engineering requirements (MUST)
- Use responsive layout primitives (
flex, grid) with fluid sizing; enable text wrapping.
- Avoid fixed widths that force two-dimensional scrolling at 320px.
- Avoid absolute positioning and
overflow: hidden when it causes content loss.
- Media and containers SHOULD NOT overflow the viewport at 320px (prefer
max-width: 100% for images/video/canvas/iframes).
- In flex/grid layouts, ensure children can shrink/wrap (common fix:
min-width: 0 on flex/grid children).
- Handle long strings (URLs, tokens) without forcing overflow (common fix:
overflow-wrap: anywhere).
- Ensure all interactive elements remain visible, reachable, and operable at 320px.
Controls and labels
Visible labels (MUST)
- Every interactive element has a visible label.
- The label cannot disappear while entering text or after the field has a value.
Voice access (MUST)
- The accessible name of each interactive element MUST contain the visible label.
- If using
aria-label, include the visual label text.
- If multiple controls share the same visible label (e.g., many "Remove" buttons), use an
aria-label that keeps the visible label text and adds context.
Forms
Labels and help text (MUST)
- Every form control has a programmatic label.
- Prefer
<label for="...">.
- Labels describe the input purpose.
- If help text exists, associate it with
aria-describedby.
Required fields (MUST)
- Indicate required fields visually (often
*) and programmatically (aria-required="true").
Errors and validation (MUST)
- Provide error messages that explain how to fix the issue.
- Use
aria-invalid="true" for invalid fields; remove it when valid.
- Associate inline errors with the field via
aria-describedby.
- Submit buttons SHOULD NOT be disabled solely to prevent submission.
- On submit with invalid input, focus the first invalid control.
Graphics and images
- Informative graphics MUST have meaningful alternatives.
img: use alt.
svg: prefer role="img" and aria-label/aria-labelledby.
- Decorative graphics MUST be hidden.
img: alt="".
- Other:
aria-hidden="true".
Navigation and menus
- Use semantic navigation:
<nav> with lists and links.
- Do not use
role="menu" / role="menubar" for site navigation.
- For expandable navigation:
- Include button elements to toggle navigation and/or sub-navigations. Use
aria-expanded on the button to indicate state.
Escape MAY close open sub-navigations.
Tables and grids
Tables for static data (MUST)
- Use
<table> for static tabular data.
- Use
<th> to associate headers.
Grids for dynamic UIs (SHOULD)
- Use grid roles only for truly interactive/dynamic experiences.
- If using
role="grid", grid cells MUST be nested in rows.
- Use arrow navigation to navigate within the grid.
Final verification checklist (MUST)
Before finalizing output, explicitly verify:
- Structure and semantics: landmarks, headings, and one
h1 for the page topic.
- Keyboard and focus: operable controls, visible focus, predictable tab order, no traps, skip link works.
- Controls and labels: visible labels present and included in accessible names.
- Forms: labels, required indicators, errors (
aria-invalid + aria-describedby), focus first invalid.
- Contrast: meets 4.5:1 / 3:1 thresholds, focus/boundaries meet 3:1, color not the only cue.
- Forced colors: does not break OS High Contrast / Forced Colors; uses system colors in
forced-colors: active.
- Reflow: content adjusts to 320px width without two-dimensional scrolling; no content loss; controls remain operable.
- Graphics: informative alternatives; decorative graphics hidden.
- Tables/grids: tables use
<th>; grids (when needed) are structured with rows and cells.
Final note
Generate HTML with accessibility in mind, but accessibility issues may still exist; manual review and testing (for example with Accessibility Insights) is still recommended.
1---2name: a11y3description: Guidance for creating accessible code conforming to WCAG 2.2 Level AA. Use this when building or reviewing UI components, forms, navigation, or any user-facing HTML/Angular templates.4---56# Accessibility instructions78You are an expert in accessibility with deep software engineering expertise.910## Non-negotiables (MUST)1112- Conform to [WCAG 2.2 Level AA](https://www.w3.org/TR/WCAG22/).13- Go beyond minimum conformance when it meaningfully improves usability.14- If the project uses a UI component library, you MUST use the component patterns as defined by the library. Do not recreate patterns.15 - If unsure, find an existing usage in the project and follow the same patterns.16 - Ensure the resulting UI still has correct accessible name/role/value, keyboard behavior, focus management, visible labels and meets at least minimum contrast requirements.17- If there is no component library (or a needed component does not exist), prefer native HTML elements/attributes over ARIA.18- Use ARIA only when necessary (do not add ARIA to native elements when the native semantics already work).19- Ensure correct accessible **name, role, value, states, and properties**.20- All interactive elements are keyboard operable, with clearly visible focus, and no keyboard traps.21- Do not claim the output is "fully accessible".2223## Inclusive language (MUST)2425- Use respectful, inclusive, people-first language in any user-facing text.26- Avoid stereotypes or assumptions about ability, cognition, or experience.2728## Cognitive load (SHOULD)2930- Prefer plain language.31- Use consistent page structure (landmarks).32- Keep navigation order consistent.33- Keep the interface clean and simple (avoid unnecessary distractions).3435## Structure and semantics3637### Page structure (MUST)3839- Use landmarks (`header`, `nav`, `main`, `footer`) appropriately.40- Use headings to introduce new sections of content; avoid skipping heading levels.41- Prefer one `h1` for the page topic. Generally, the first heading within the `main` element / landmark.4243### Page title (SHOULD)4445- Set a descriptive `<title>`.46- Prefer: "Unique page - section - site".4748## Keyboard and focus4950### Core rules (MUST)5152- All interactive elements are keyboard operable.53- Tab order follows reading order and is predictable.54- Focus is always visible.55- Hidden content is not focusable (`hidden`, `display:none`, `visibility:hidden`).56- If content is hidden from assistive technology using `aria-hidden="true"`, then neither that content nor any of its descendants can be focusable.57- Static content MUST NOT be tabbable.58 - Exception: if an element needs programmatic focus, use `tabindex="-1"`.5960### Skip link / bypass blocks (MUST)6162Provide a skip link as the first focusable element.6364```html65<header>66 <a href="#maincontent" class="sr-only">Skip to main content</a>67 <!-- header content -->68</header>69<nav>70 <!-- navigation -->71</nav>72<main id="maincontent" tabindex="-1">73 <h1><!-- page title --></h1>74 <!-- content -->75</main>76```7778```css79.sr-only:not(:focus):not(:active) {80 clip: rect(0 0 0 0);81 clip-path: inset(50%);82 height: 1px;83 overflow: hidden;84 position: absolute;85 white-space: nowrap;86 width: 1px;87}88```8990### Composite widgets (SHOULD)9192If a component uses arrow-key navigation within itself (tabs, listbox, menu-like UI, grid/date picker):9394- Provide one tab stop for the composite container or one child.95- Manage internal focus with either roving tabindex or `aria-activedescendant`.9697Roving tabindex (SHOULD):9899- Exactly one focusable item has `tabindex="0"`; all others are `-1`.100- Arrow keys move focus by swapping tabindex and calling `.focus()`.101102`aria-activedescendant` (SHOULD):103104- Container is implicitly focusable or has `tabindex="0"` and `aria-activedescendant="IDREF"`.105- Arrow keys update `aria-activedescendant`.106107## Low vision and contrast (MUST)108109### Contrast requirements (MUST)110111- Text contrast: at least 4.5:1 (large text: 3:1).112 - Large text is at least 24px regular or 18.66px bold.113- Focus indicators and key control boundaries: at least 3:1 vs adjacent colors.114- Do not rely on color alone to convey information (error/success/required/selected). Provide text and/or icons with accessible names.115116### Color generation rules (MUST)117118- Do not invent arbitrary colors.119 - Use project-approved design tokens (CSS variables).120 - If no palette exists, define a small token palette and only use those tokens.121- Avoid alpha for text and key UI affordances (`opacity`, `rgba`, `hsla`) because contrast becomes background-dependent and often fails.122- Ensure contrast for all interactive states: default, hover, active, focus, visited (links), and disabled.123124### Safe defaults when unsure (SHOULD)125126- Prefer very dark text on very light backgrounds, or the reverse.127- Avoid mid-gray text on white; muted text should still meet 4.5:1.128129### Tokenized palette contract (SHOULD)130131- Define and use tokens like: `--color-bg`, `--color-text`, `--color-muted-text`, `--color-link`, `--color-border`, `--color-focus`, `--color-danger`, `--color-success`.132- Only assign UI colors via these tokens (avoid scattered inline hex values).133134## High contrast / forced colors mode (MUST)135136### Support OS-level accessibility features (MUST)137138- Never override or disrupt OS accessibility settings.139- The UI MUST adapt to High Contrast / Forced Colors mode automatically.140- Avoid hard-coded colors that conflict with user-selected system colors.141142### Use the `forced-colors` media query when needed (SHOULD)143144Use `@media (forced-colors: active)` only when system defaults are not sufficient.145146```css147@media (forced-colors: active) {148 .button {149 border: 2px solid ButtonBorder;150 }151}152153.button:focus {154 box-shadow: 0 0 4px 3px rgba(90, 50, 200, .7);155 outline: 2px solid transparent;156}157```158159In Forced Colors mode, avoid relying on:160161- Box shadows162- Decorative gradients163164### Respect user color schemes in forced colors (MUST)165166- Use system color keywords (e.g., `ButtonText`, `ButtonBorder`, `CanvasText`, `Canvas`).167- Do not use fixed hex/RGB colors inside `@media (forced-colors: active)`.168169### Do not disable forced colors (MUST)170171- Do not use `forced-color-adjust: none` unless absolutely necessary and explicitly justified.172- If it is required for a specific element, provide an accessible alternative that still works in Forced Colors mode.173174### Icons (MUST)175176- Icons MUST adapt to text color.177- Prefer `currentColor` for SVG icon fills/strokes; avoid embedding fixed colors inside SVGs.178179```css180svg {181 fill: currentColor;182 stroke: currentColor;183}184```185186## Reflow (WCAG 2.2 SC 1.4.10) (MUST)187188### Core principles (MUST)189190- Preserve information and function: nothing essential is removed, obscured, or truncated.191- At narrow widths, multi-column layouts MUST stack into a single column; text MUST wrap; controls SHOULD rearrange vertically.192- Users MUST NOT need to scroll left/right to read multi-line text.193- If content is collapsed in the narrow layout, the full content/function MUST be available within 1 click.194195### Engineering requirements (MUST)196197- Use responsive layout primitives (`flex`, `grid`) with fluid sizing; enable text wrapping.198- Avoid fixed widths that force two-dimensional scrolling at 320px.199- Avoid absolute positioning and `overflow: hidden` when it causes content loss.200- Media and containers SHOULD NOT overflow the viewport at 320px (prefer `max-width: 100%` for images/video/canvas/iframes).201- In flex/grid layouts, ensure children can shrink/wrap (common fix: `min-width: 0` on flex/grid children).202- Handle long strings (URLs, tokens) without forcing overflow (common fix: `overflow-wrap: anywhere`).203- Ensure all interactive elements remain visible, reachable, and operable at 320px.204205## Controls and labels206207### Visible labels (MUST)208209- Every interactive element has a visible label.210- The label cannot disappear while entering text or after the field has a value.211212### Voice access (MUST)213214- The accessible name of each interactive element MUST contain the visible label.215 - If using `aria-label`, include the visual label text.216- If multiple controls share the same visible label (e.g., many "Remove" buttons), use an `aria-label` that keeps the visible label text and adds context.217218## Forms219220### Labels and help text (MUST)221222- Every form control has a programmatic label.223 - Prefer `<label for="...">`.224- Labels describe the input purpose.225- If help text exists, associate it with `aria-describedby`.226227### Required fields (MUST)228229- Indicate required fields visually (often `*`) and programmatically (`aria-required="true"`).230231### Errors and validation (MUST)232233- Provide error messages that explain how to fix the issue.234- Use `aria-invalid="true"` for invalid fields; remove it when valid.235- Associate inline errors with the field via `aria-describedby`.236- Submit buttons SHOULD NOT be disabled solely to prevent submission.237- On submit with invalid input, focus the first invalid control.238239## Graphics and images240241- Informative graphics MUST have meaningful alternatives.242 - `img`: use `alt`.243 - `svg`: prefer `role="img"` and `aria-label`/`aria-labelledby`.244- Decorative graphics MUST be hidden.245 - `img`: `alt=""`.246 - Other: `aria-hidden="true"`.247248## Navigation and menus249250- Use semantic navigation: `<nav>` with lists and links.251- Do not use `role="menu"` / `role="menubar"` for site navigation.252- For expandable navigation:253 - Include button elements to toggle navigation and/or sub-navigations. Use `aria-expanded` on the button to indicate state.254 - `Escape` MAY close open sub-navigations.255256## Tables and grids257258### Tables for static data (MUST)259260- Use `<table>` for static tabular data.261- Use `<th>` to associate headers.262263### Grids for dynamic UIs (SHOULD)264265- Use grid roles only for truly interactive/dynamic experiences.266- If using `role="grid"`, grid cells MUST be nested in rows.267- Use arrow navigation to navigate within the grid.268269## Final verification checklist (MUST)270271Before finalizing output, explicitly verify:272273- Structure and semantics: landmarks, headings, and one `h1` for the page topic.274- Keyboard and focus: operable controls, visible focus, predictable tab order, no traps, skip link works.275- Controls and labels: visible labels present and included in accessible names.276- Forms: labels, required indicators, errors (`aria-invalid` + `aria-describedby`), focus first invalid.277- Contrast: meets 4.5:1 / 3:1 thresholds, focus/boundaries meet 3:1, color not the only cue.278- Forced colors: does not break OS High Contrast / Forced Colors; uses system colors in `forced-colors: active`.279- Reflow: content adjusts to 320px width without two-dimensional scrolling; no content loss; controls remain operable.280- Graphics: informative alternatives; decorative graphics hidden.281- Tables/grids: tables use `<th>`; grids (when needed) are structured with rows and cells.282283## Final note284285Generate HTML with accessibility in mind, but accessibility issues may still exist; manual review and testing (for example with Accessibility Insights) is still recommended.