Accessibility guidelines

WCAG 2.2 AA standards for semantic HTML, keyboard access, ARIA, forms, and contrast — with or without Duo.

Accessibility guidelines

Accessible interfaces work for keyboard-only users, screen reader users, and people with low vision or color-vision differences. Follow WCAG 2.2 AA by default.

Install the standalone agent skill for AI-assisted work: npx skills add https://design.talentech.io → choose accessible-frontend.

Core principles

Semantic HTML first

  • Use native HTML elements (<button>, <nav>, <main>, <article>, <dialog>) instead of <div> or <span> with click handlers.
  • Use correct heading hierarchy (<h1> through <h6>) without skipping levels.

Keyboard accessibility

  • All interactive elements must be focusable and operable via keyboard (Tab, Enter, Space, Arrows).
  • Provide visible focus indicators (:focus-visible). Never use outline: none without a custom focus style.

ARIA

  • Rule of thumb: No ARIA is better than bad ARIA. Use native HTML elements whenever possible.
  • Use aria-label or aria-labelledby when a visual label is missing.
  • Use aria-expanded, aria-hidden, aria-controls, and aria-live for dynamic content and state changes.

Color and contrast

  • Ensure text has a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text.
  • Do not rely on color alone to convey information — combine with icons or text for errors, success, and status.

Forms and inputs

  • Every <input>, <select>, and <textarea> must have an associated <label>.
  • Use aria-describedby to link inputs to error messages or helper text.
  • Group related radio buttons and checkboxes with <fieldset> and <legend>.

See also Form guidelines and Error messages.

Images and media

  • Provide meaningful alt text for informative images.
  • Use alt="" for purely decorative images so screen readers ignore them.

Examples

Button

<!-- Bad -->
<div class="btn" onclick="submitForm()">Submit</div>
<!-- Good -->
<button type="submit" class="btn">Submit</button>

Form input with error

<!-- Bad -->
<input type="text" placeholder="Email address" />
<span class="error">Invalid email</span>
<!-- Good -->
<label for="email">Email address</label>
<input type="email" id="email" aria-describedby="email-error" aria-invalid="true" />
<span id="email-error" class="error" role="alert">Invalid email format</span>

Icon button

<!-- Bad -->
<button><svg>...</svg></button>
<!-- Good -->
<button aria-label="Close dialog"><svg aria-hidden="true">...</svg></button>
<dialog aria-labelledby="dialog-title" aria-modal="true">
<h2 id="dialog-title">Confirm Action</h2>
<p>Are you sure you want to proceed?</p>
<button autofocus>Confirm</button>
<button>Cancel</button>
</dialog>
<nav aria-label="Main navigation">
<ul>
<li><a href="/" aria-current="page">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>

Review checklist

Before shipping frontend code, verify:

  • All interactive elements are native or properly role-assigned
  • Component is fully operable with keyboard only
  • Focus states are clearly visible
  • All inputs have associated labels
  • Dynamic state changes are announced to screen readers
  • Color contrast meets 4.5:1 (normal text) or 3:1 (large text)
  • Images have appropriate alt text
  • No color is used as the sole indicator of meaning

With Duo

When building with the Duo Design System:

  • Prefer <duo-*> web components over bespoke markup for standard patterns — they ship keyboard support, focus styles, and accessible names.
  • Use <duo-field> with native controls in the light DOM; follow markup order in Form guidelines.
  • Set accessible names on icon-only controls (aria-label on <duo-button>, accessibleLabel where documented).
  • Use semantic design tokens (var(--duo-*)) for focus and state — not hardcoded colors.
  • Check each component’s accessibility section under Components.

Install Duo agent skills: npx skills add https://design.talentech.io → choose build-with-duo and audit-duo-conformance. Add accessible-frontend for broader WCAG coverage beyond Duo patterns.