---
title: "Focus outline removed without a visible replacement (lint/outline-none-no-replacement)"
description: "lint/outline-none-no-replacement: `outline: none` / `outline-none` hides the keyboard focus indicator."
canonical: https://void-design.vercel.app/rules/lint/outline-none-no-replacement
lastModified: 2026-09-16
---

# Focus outline removed without a visible replacement

`lint/outline-none-no-replacement` · severity **warn** · category Lint · detected by `void lint` and `void audit`

## Why it matters

`outline: none` / `outline-none` hides the keyboard focus indicator. Keyboard users lose track of where they are, and it fails WCAG 2.4.7 (Focus Visible).

## How to fix it

Pair it with a `:focus-visible` style (ring, border or shadow), or leave the default outline and only style `:focus-visible`.

## Example

```tsx
<input className="outline-none focus-visible:ring-2 focus-visible:ring-(--line-focus) focus-visible:ring-offset-2" />
```

## References

- https://www.w3.org/WAI/WCAG22/Understanding/focus-visible.html

## More lint rules

`void lint` reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.

- `div-button` Clickable `<div>`/`<span>` without button semantics — [lint/div-button](https://void-design.vercel.app/rules/lint/div-button)
- `dangerously-set-jsonld-unescaped` JSON-LD injected with `JSON.stringify` without escaping `<` — [lint/dangerously-set-jsonld-unescaped](https://void-design.vercel.app/rules/lint/dangerously-set-jsonld-unescaped)
- `transition-all` `transition: all` / `transition-all` — [lint/transition-all](https://void-design.vercel.app/rules/lint/transition-all)
- `animate-layout-prop` Animation of layout properties (width/height/top/left/margin/padding) — [lint/animate-layout-prop](https://void-design.vercel.app/rules/lint/animate-layout-prop)
- `scale-zero-entry` Element enters from `scale(0)` — [lint/scale-zero-entry](https://void-design.vercel.app/rules/lint/scale-zero-entry)
- `scroll-timeline-no-fallback` Base rule hides an element; only an `@supports (animation-timeline: …)` block undoes it — [lint/scroll-timeline-no-fallback](https://void-design.vercel.app/rules/lint/scroll-timeline-no-fallback)
- `ease-in-enter` `ease-in` used for an entrance or hover — [lint/ease-in-enter](https://void-design.vercel.app/rules/lint/ease-in-enter)
- `long-ui-duration` UI feedback transition longer than 500ms — [lint/long-ui-duration](https://void-design.vercel.app/rules/lint/long-ui-duration)

Detected by `void lint` and `void audit`. Explain it in a terminal: `void rules lint/outline-none-no-replacement`
