Help us improve
Share bugs, ideas, or general feedback.
Ensures WCAG 2.2 AA web accessibility: color contrast ratios (4.5:1 body text), keyboard navigation, ARIA attributes, focus indicators, screen reader support, color independence, and axe-core testing.
npx claudepluginhub oborchers/fractional-cto --plugin visual-design-principlesHow this skill is triggered — by the user, by Claude, or both
Slash command
/visual-design-principles:accessibility-inclusive-designThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
16% of the global population has a disability (WHO). Accessibility is not an edge case -- it is a core design quality dimension. WCAG 2.2 AA compliance is the minimum bar, not a stretch goal. Inaccessible design is broken design.
Audits and improves web accessibility following WCAG 2.2 guidelines, including POUR principles, alt text for images/icons, color contrast, and focus states. Use for a11y audits and compliance.
Audits designs for WCAG 2.2 AA violations (contrast, focus, target size, keyboard semantics, motion, cognition). Auto-activates on designer tasks.
Enforces WCAG AA and ARIA best practices for screen readers, keyboard navigation, and focus management. Use when building or auditing user-facing interfaces for accessibility compliance.
Share bugs, ideas, or general feedback.
16% of the global population has a disability (WHO). Accessibility is not an edge case -- it is a core design quality dimension. WCAG 2.2 AA compliance is the minimum bar, not a stretch goal. Inaccessible design is broken design.
| Principle | Requirement | Key Rules |
|---|---|---|
| Perceivable | All content perceivable by all users | Text alternatives, captions, sufficient contrast, no color-only meaning |
| Operable | All functionality operable via all input methods | Keyboard accessible, no time traps, skip links, focus indicators |
| Understandable | Content and operation are understandable | Plain language, consistent navigation, specific error messages |
| Robust | Content works with current and future technologies | Valid HTML, ARIA roles used correctly, tested across assistive tech |
| Element | Minimum Ratio (AA) | AAA Target | Tool |
|---|---|---|---|
| Body text (<18px / <14px bold) | 4.5:1 | 7:1 | WebAIM Contrast Checker |
| Large text (>=18px / >=14px bold) | 3:1 | 4.5:1 | Chrome DevTools |
| Non-text elements (icons, borders, focus rings) | 3:1 | -- | axe-core |
| Disabled elements | Exempt | -- | -- |
| Decorative elements | Exempt | -- | -- |
Practical rule: Test every foreground/background combination. Gray text on white is the most common failure -- #767676 on #fff is the lightest gray that passes 4.5:1.
Never rely on color alone to convey meaning. Provide redundant encoding for every color-coded element.
| Context | Bad (Color Only) | Good (Redundant Encoding) |
|---|---|---|
| Status indicators | Red dot / green dot | Red dot + "Error" label / green dot + checkmark icon |
| Form validation | Red border on invalid field | Red border + error icon + error message text |
| Charts and data viz | Color-coded lines only | Color + pattern (dash, dot) + labeled legend |
| Links in body text | Color difference only | Color + underline (or underline on hover minimum) |
| Alerts and banners | Background color only | Background color + icon + role="alert" |
Never remove :focus outlines without providing a replacement. Use :focus-visible to show focus rings only for keyboard users.
| Rule | Implementation |
|---|---|
Never use outline: none without replacement | Remove only if custom focus style is applied |
Use :focus-visible over :focus | Prevents focus rings on mouse clicks |
| Minimum focus ring | 3px solid with 2px offset in high-contrast color |
| Focus must be visible on all backgrounds | Test on light, dark, and colored backgrounds |
| Focus order must match visual order | Use tabindex="0", avoid positive tabindex values |
| Requirement | Implementation |
|---|---|
| All interactive elements reachable via Tab | Buttons, links, inputs, selects, custom widgets |
| Logical tab order | Matches visual left-to-right, top-to-bottom flow |
| Skip link as first focusable element | <a href="#main" class="skip-link">Skip to content</a> |
| Escape closes modals/dropdowns | Return focus to the trigger element |
| Arrow keys for composite widgets | Tabs, menus, radio groups, listboxes |
| No keyboard traps | Every focusable area can be exited via Tab or Escape |
Minimum touch target size is 44x44px (WCAG 2.2 Level AA). Maintain 8px minimum spacing between adjacent targets to prevent accidental activation.
| Element | Minimum Size | Minimum Spacing |
|---|---|---|
| Buttons | 44x44px | 8px |
| Links in navigation | 44px height | 8px vertical gap |
| Icon buttons | 44x44px (padding around smaller icons) | 8px |
| Inline text links | Exempt (but avoid dense clusters) | -- |
| Guideline | Rule |
|---|---|
| Heading hierarchy | h1 through h6 in logical order -- never skip levels |
| Landmark regions | <header>, <nav>, <main>, <footer>, <aside> on every page |
| Alt text strategy | Informative images: describe content. Decorative images: alt="". Complex images: aria-describedby linking to long description |
| Button labels | Avoid "Click here" -- use descriptive labels: "Download invoice PDF" |
| Form labels | Every input has a visible <label> with matching for/id |
| Live regions | aria-live="polite" for status updates, aria-live="assertive" for errors |
| Hidden content | Use aria-hidden="true" for decorative elements, sr-only class for screen-reader-only text |
| Tool | Catches | Limitation |
|---|---|---|
| axe-core | ~30% of WCAG issues: contrast, missing labels, ARIA misuse | Cannot test visual layout, reading order, keyboard flow |
| Lighthouse Accessibility | Same engine as axe-core, scores 0-100 | Score of 100 does not mean accessible |
| WAVE | Visual overlay of issues on page | Cannot test dynamic content |
Automated tools catch 30-50% of issues. Manual testing is required for: keyboard navigation flow, screen reader experience, focus management in dynamic content, reading order, and cognitive clarity.
| Anti-Pattern | Why It Fails | Fix |
|---|---|---|
| Color-only status indicators | Invisible to colorblind users (8% of males) | Add icon + text label |
outline: none without replacement | Keyboard users cannot see focus | Use :focus-visible with custom ring |
| Placeholder-only labels | Disappear on input; not announced by all screen readers | Use visible <label> elements |
| Auto-playing video/audio | Disorienting; cannot be stopped by keyboard alone | Require user-initiated play |
| Missing heading hierarchy | Screen reader users cannot navigate by headings | Use h1-h6 in logical order |
div and span as buttons | No keyboard support, no screen reader role | Use <button> or add role="button" + tabindex="0" + keyboard handler |
Positive tabindex values | Breaks natural focus order | Use tabindex="0" or -1 only |
Working implementations in examples/:
examples/accessible-form-and-focus.md -- Accessible form with proper labels, focus indicators, error messaging, and ARIA attributes in CSS/HTML/ReactWhen reviewing or building for accessibility:
:focus-visible used instead of :focus where appropriateheader, nav, main, footer)<label> with matching for/idaria-describedby