---
name: accessible-focus-states
title: Accessible Focus States
description: Keep a visible, high-contrast focus indicator on every interactive element, without a generic browser outline or none at all.
author:
name: UI Skillbook
url: https://uiskillbook.com
categories:
- accessibility
- interaction
agents:
- claude-code
- codex
- cursor
- opencode
- universal
tasks:
- form
- navigation
- design-system
tags:
- accessibility
- keyboard
- focus
version: 1.0.0
updated_at: "2026-09-01"
license: MIT
curated: true
---
# Accessible Focus States
`outline: none` without a replacement is the single most common accessibility regression in hand-built UI. It doesn't just fail an audit — it makes the interface unusable for anyone navigating by keyboard.
## When to use
- Every interactive element: links, buttons, form fields, custom checkboxes/radios, menu items, tabs.
- Especially custom components built from `
`s that don't get a native focus ring for free.
## Principles
- Focus indication and hover indication are different states with different purposes — don't conflate them. Hover shows "you could click this," focus shows "keyboard input goes here right now."
- Use `:focus-visible` instead of `:focus` so the ring appears for keyboard navigation but not on every mouse click (matches user expectation without visual noise).
- Focus rings need at least 3:1 contrast against the adjacent background (WCAG 2.2 non-text contrast).
## Instructions
1. Never remove the default outline (`outline: none`) without providing a replacement that meets contrast requirements.
2. Style with `:focus-visible`, and provide a `:focus` fallback only for browsers that don't support it.
3. Offset the ring 2px from the element (`outline-offset: 2px`) so it doesn't get clipped by `overflow: hidden` containers or blend into the element's own border.
4. For custom components (div-based dropdowns, custom checkboxes), verify `tabindex` and ARIA roles are correct *before* styling focus — a ring on an unfocusable element is meaningless.
5. Test the full page by tabbing through it with the mouse untouched. Every interactive element must be reachable and visibly focused, in a logical order.
## Examples
```css
.control:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
```
## Avoid
- Don't use `box-shadow` alone for focus if it can be hidden by neighboring elements' stacking context — verify it's actually visible in context.
- Don't style focus and hover identically; users need to distinguish "I'm pointing at this" from "this is where my keystrokes go."
## References
- WCAG 2.2 Success Criterion 2.4.11 (Focus Not Obscured) and 1.4.11 (Non-text Contrast).