Patterns for ensuring interfaces are usable by everyone.
Core principle: Accessibility is not a checklist item—it's a design approach.
What: Full functionality without a mouse.
| Pattern | Keyboard Support |
|---|---|
| Focus order | Tab moves logically through page |
| Focus visible | Current focus always visible |
| Activation | Enter/Space activates buttons/links |
| Navigation | Arrow keys navigate within components |
| Escape | Escape closes modals/popups |
| Shortcuts | Common shortcuts available |
DO:
DON'T:
/* Visible, high contrast focus */
:focus-visible {
outline: 2px solid #2563eb;
outline-offset: 2px;
}
/* Remove default only when custom is applied */
button:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.5);
}
What: Accessible Rich Internet Applications—additional semantics for assistive technology.
| Attribute | Purpose | Example |
|---|---|---|
aria-label |
Accessible name | <button aria-label="Close">×</button> |
aria-describedby |
Additional description | Links to help text |
aria-hidden |
Hide from assistive tech | Decorative elements |
aria-expanded |
Toggle state | Accordions, dropdowns |
aria-selected |
Selection state | Tabs, list items |
aria-live |
Announce changes | Dynamic content |
aria-invalid |
Invalid state | Form validation |
aria-required |
Required field | Form fields |
Button with icon only:
<button aria-label="Delete item">
<svg aria-hidden="true">...</svg>
</button>
Accordion:
<button aria-expanded="false" aria-controls="panel1">
Section Title
</button>
<div id="panel1" hidden>Content...</div>
Live region:
<div aria-live="polite" aria-atomic="true">
<!-- Content changes announced by screen reader -->
</div>
What: Text equivalents for non-text content.
Informative images:
Decorative images:
alt=""aria-hidden="true"Functional images (buttons/links):
Complex images:
aria-describedby to link| Image | Bad Alt | Good Alt |
|---|---|---|
| Logo | "Logo" | "Acme Corp" |
| Search icon | "Magnifying glass" | "Search" |
| Product photo | "Photo" | "Blue cotton t-shirt, front view" |
| Decorative border | "Border" | alt="" (empty) |
| Chart | "Chart" | "Sales increased 25% from Q1 to Q2" + full data table |
What: Ensuring content is perceivable regardless of color vision.
| Content | Minimum Ratio | Target Ratio |
|---|---|---|
| Normal text | 4.5:1 | 7:1 (AAA) |
| Large text (18px+) | 3:1 | 4.5:1 (AAA) |
| UI components | 3:1 | 4.5:1 |
| Focus indicators | 3:1 | 4.5:1 |
DO:
DON'T:
✓ Success (green check icon + green color)
✗ Error (red X icon + red color + border)
! Warning (yellow triangle icon + yellow background)
What: Ensuring text is readable by all users.
Font size:
Line length:
Line height:
Font choice:
Text resizing:
What: Making interactive elements accessible.
| Element | Minimum Size | Target Size |
|---|---|---|
| Touch targets | 44x44px | 48x48px |
| Click targets | 24x24px | 32x32px |
| Spacing between | 8px | 12px |
Links:
Buttons:
Forms:
What: Respecting user preferences for reduced motion.
DO:
prefers-reduced-motionDON'T:
@media (prefers-reduced-motion: reduce) {
* {
animation: none !important;
transition: none !important;
}
}
What: Verifying experience for screen reader users.
☐ All images have appropriate alt text ☐ Headings create logical outline (H1 → H2 → H3) ☐ Links and buttons have descriptive names ☐ Form labels are associated with inputs ☐ Error messages are announced ☐ Dynamic content changes are announced ☐ Focus management works after interactions ☐ Page title is descriptive
| Category | Requirements |
|---|---|
| ☐ Keyboard | All functions keyboard accessible |
| ☐ Focus | Visible focus indicators |
| ☐ Semantics | Proper HTML elements + ARIA |
| ☐ Images | Alt text for all meaningful images |
| ☐ Color | Not the only differentiator |
| ☐ Contrast | 4.5:1 for text, 3:1 for UI |
| ☐ Text | Resizable, readable, proper hierarchy |
| ☐ Motion | Reducible, not seizure-inducing |
| ☐ Forms | Labels, errors, required indicators |
| ☐ Testing | Verified with screen reader |