# Focus indicator is visible with sufficient contrast

- **Pattern:** `ab-000056` (`accessibility-basics.keyboard-focus.focus-indicator-contrast`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000056
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000056)

## Why it matters

A focus indicator removed by `outline: none` in a CSS reset — one of the most ubiquitous accessibility mistakes — means that a sighted keyboard user cannot determine which element is active. Without knowing where focus is, they cannot predict what Enter or Space will do. WCAG 2.2 SC 2.4.7 (Focus Visible) is a long-standing Level AA requirement; SC 2.4.11 (Focus Appearance) in WCAG 2.2 adds minimum geometric constraints: the focus indicator must have a contrast ratio of at least 3:1 against adjacent colors and must enclose a perimeter of at least the CSS `outline` equivalent. SC 1.4.11 (Non-text Contrast) governs UI component contrast. Section 508 2018 Refresh 302.7 requires visual accessibility. The specific failure: Tailwind's `ring` utility defaults to a `ring-offset` that is invisible on dark backgrounds, creating a technically-present but practically-invisible focus indicator.

## Severity rationale

Critical because invisible focus indicators make keyboard navigation completely unusable for sighted keyboard users, affecting millions of users who rely on keyboard navigation.

## Remediation

Audit your `globals.css` and component files for `outline: none` without a replacement focus style. Add a global `focus-visible` style as a safety net, then override per component as needed.

```css
/* globals.css — safety net */
*:focus-visible {
  outline: 3px solid #0066cc;
  outline-offset: 3px;
}

/* If using Tailwind, add to base layer in globals.css */
@layer base {
  *:focus-visible {
    @apply outline-none ring-2 ring-blue-600 ring-offset-2;
  }
}

/* For dark backgrounds, ensure ring is visible */
.dark *:focus-visible {
  @apply ring-blue-400 ring-offset-gray-900;
}

/* Never do this without a replacement: */
/* button:focus { outline: none; } */
```

Verify using browser DevTools: tab to each interactive element and use the computed styles inspector to confirm a visible outline or ring is applied. The contrast ratio between the focus indicator color and the background must be at least 3:1 per WCAG 2.2 SC 2.4.11.

## Detection

- **ID:** `focus-indicator-contrast`
- **Severity:** `critical`
- **What to look for:** Tab through all interactive elements and visually inspect the focus indicator. Check that the outline or highlight is clearly visible against the background. Look for `outline: none` or very faint focus styles.
- **Pass criteria:** Every interactive element displays a visible focus indicator. The indicator has a contrast ratio of at least 3:1 against the background. No elements use `outline: none` without a visible replacement style.
- **Fail criteria:** Focus indicator is missing, invisible, or has less than 3:1 contrast. Any element uses `outline: none` without a replacement focus style.
- **Skip (N/A) when:** Never — focus indicators apply to all interactive pages.
- **Detail on fail:** Describe the focus visibility issue. Example: `"Focus outline removed with outline: none. Many buttons have gray outline on gray background with insufficient contrast. Focus indicator only 1px thin and hard to see."`
- **Remediation:** Provide clear, high-contrast focus indicators:

  ```css
  button:focus {
    outline: 3px solid #0066cc;
    outline-offset: 2px;
  }

  /* Or use a background color change */
  button:focus {
    background-color: #e6f0ff;
    border: 2px solid #0066cc;
  }

  /* Modern: use :focus-visible for keyboard focus only */
  button:focus-visible {
    outline: 3px solid #0066cc;
    outline-offset: 2px;
  }
  ```

## External references

- wcag 2.4.11
- wcag 2.4.7
- wcag 1.4.11
- section-508 302.7

Taxons: accessibility

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