← Back to Docs
Recipe

Focus Ring Design Patterns

Accessible, beautiful focus indicators that work across keyboard, mouse, and touch without compromising your visual design.

The Baseline

Browsers ship default focus rings. They work. They are also ugly and inconsistent. The goal is to replace them with something that feels intentional while preserving — or improving — accessibility.

/* Reset default, then rebuild */
*:focus {
  outline: none;
}

*:focus-visible {
  outline: 2px solid #8B5CF6;
  outline-offset: 2px;
  border-radius: 4px;
}

The critical distinction: :focus fires for mouse clicks too. :focus-visible only fires when the browser heuristics detect keyboard navigation. Always use focus-visible for rings.

The Glow Variant

For dark interfaces, a box-shadow glow reads better than a hard outline. It blends into the design language instead of fighting it.

*:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.5);
  border-radius: 6px;
}

The Ring-Offset Pattern

A two-layer approach: a thin inner ring plus a translucent outer glow. This works on any background and looks premium.

*:focus-visible {
  outline: none;
  box-shadow:
    0 0 0 2px #0A0612,
    0 0 0 4px #8B5CF6;
  border-radius: 4px;
}

Tailwind Utility Class

Encapsulate the pattern into a reusable class so every interactive element gets consistent treatment.

/* globals.css */
@layer utilities {
  .focus-ring {
    @apply focus:outline-none focus-visible:ring-2
           focus-visible:ring-[#8B5CF6]
           focus-visible:ring-offset-2
           focus-visible:ring-offset-[#0A0612]
           focus-visible:rounded;
  }
}

Interactive Elements

Apply the utility to links, buttons, inputs, and any custom interactive component. Consistency is the point.

Link with focus ring

Never Do This

  • outline: none without replacing it. This breaks keyboard navigation entirely.
  • Using :focus for decorative rings. Mouse users will see flashes on every click.
  • Low-contrast rings. A 1px gray ring on a dark background is invisible to low-vision users.