# Focus indicator is visible on all interactive elements

- **Pattern:** `ab-000106` (`accessibility-wcag.operable.focus-visible`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000106
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000106)

## Why it matters

Removing focus indicators with `outline: none` without a replacement makes keyboard navigation invisible. Users who cannot use a mouse — including those with motor disabilities, power users, and anyone without a pointing device — lose their only visual cue for where focus is on the page. WCAG 2.2 SC 2.4.11 (Focus Appearance) at Level AA requires focus indicators to have at least 3:1 contrast against adjacent colors. SC 2.4.7 at Level AA also requires that keyboard focus is always visible.

## Severity rationale

High because invisible focus indicators make keyboard navigation non-functional, completely excluding motor-impaired users who rely on Tab navigation to operate the interface — a WCAG 2.2 SC 2.4.11 violation.

## Remediation

Replace every `outline: none` or Tailwind `outline-none` with a custom focus style. Use `:focus-visible` so mouse users are not affected.

```css
/* Remove this from global styles */
*:focus { outline: none; }

/* Replace all outline removals with visible styles */
.btn:focus-visible {
  outline: 2px solid #4f46e5;
  outline-offset: 2px;
}
```

In Tailwind, replace `outline-none` with:

```tsx
className="... focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2"
```

Search your codebase for every occurrence of `outline: none`, `outline: 0`, and the Tailwind class `outline-none`. Each must be paired with an explicit replacement focus style that meets 3:1 contrast against adjacent colors per WCAG 2.2 SC 2.4.11.

## Detection

- **ID:** `focus-visible`
- **Severity:** `high`
- **What to look for:** Count all locations where `outline: none`, `outline: 0`, or `outline-none` (Tailwind) appear in global CSS, component styles, and utility classes. For each, verify a replacement focus style exists (`:focus-visible` or `:focus` pseudo-class with border, box-shadow, or outline with offset). Verify that focus indicators have at least 3:1 contrast ratio against adjacent colors per WCAG 2.4.11.
- **Pass criteria:** Count all outline-removal declarations found. 100% of outline removals are accompanied by a visible replacement focus style. Focus indicator contrast is at least 3:1 against adjacent colors. No more than 0 interactive elements may lack a visible focus indicator.
- **Fail criteria:** Interactive elements have `outline: none` or `outline-none` without a visible replacement focus style.
- **Skip (N/A) when:** Never.
- **Detail on fail:** `"Global CSS removes outlines with *:focus { outline: none } but provides no replacement focus style"` or `"Button component uses outline-none without focus-visible ring"`
- **Remediation:** Never remove focus indicators without providing a visible replacement:

  ```css
  /* Before — removes focus for everyone */
  button:focus { outline: none; }

  /* After — custom focus style that's visible */
  button:focus-visible {
    outline: 2px solid #4f46e5;
    outline-offset: 2px;
  }
  ```

  In Tailwind: replace `outline-none` with `focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-blue-500`.

## External references

- wcag 2.4.11
- wcag 2.4.7
- section-508 302.4

Taxons: accessibility

HTML version: https://auditbuffet.com/patterns/ab-000106
