# CSS `:focus-visible` Pseudo-class

The `:focus-visible` pseudo-class applies while an element matches the `:focus` pseudo-class *and* the user agent (browser) determines via heuristics that the focus should be made evident on the element.

## 1. The Problem with `:focus`

Traditionally, the `:focus` pseudo-class applies whenever an element receives focus, whether by keyboard (Tab key), mouse click, or touch.

This led to a common issue:
1.  Designers/Developers didn't like the default focus ring appearing when users clicked buttons with a mouse.
2.  They removed it using `outline: none`.
3.  **Result:** Keyboard users (who rely on the focus ring to know where they are) could no longer navigate the site effectively. This is a major accessibility failure.

## 2. The Solution: `:focus-visible`

`:focus-visible` solves this by letting the browser decide *when* to show the focus indicator.

*   **Keyboard Navigation:** If a user tabs to a button, `:focus-visible` matches (ring shown).
*   **Mouse Click:** If a user clicks a button, `:focus-visible` usually does *not* match (no ring shown), even though `:focus` does.
*   **Text Inputs:** Text inputs usually always match `:focus-visible` because the user needs to see the cursor/focus regardless of input method.

## 3. Basic Usage

The best practice is to remove the default outline *only* when `:focus` is active but `:focus-visible` is not, or simply define styles specifically for `:focus-visible`.

```css
/* Default focus style (often reset by browsers/frameworks) */
:focus {
  outline: 2px solid blue;
}

/* 
   Modern approach: 
   Define styles specifically for focus-visible.
   Browsers often default to this behavior now.
*/
button:focus-visible {
  outline: 2px solid blue;
  outline-offset: 2px;
}

button:focus:not(:focus-visible) {
  outline: none;
}
```

## 4. Browser Heuristics

The browser uses heuristics to determine if focus should be visible. Generally:
*   **True:** If the user interacts via keyboard (Tab, Arrow keys).
*   **True:** If the element is an `<input>`, `<textarea>`, or `contenteditable="true"` (regardless of input device).
*   **False:** If the user interacts via mouse or touch on non-text elements (buttons, links).

[[programming/css/css]]
[[programming/css/pseudo-classes-and-pseudo-elements]]
[[programming/css/selectors]]