Focus Ring Utility
Keyboard-friendly focus ring helper that applies consistent MD3 focus visibility styling to any interactive target. Not intended to replace semantic keyboard support; controls must remain natively focusable.
Basic Usage
Add data-focus-ring to mark an element for
initialization. This ensures a consistent visible focus treatment
across custom controls.
<button data-focus-ring>Default ring</button>
Initial Value
Set token overrides in markup for a customized ring.
Variants
Apply defaults, data-attribute overrides, or JavaScript options.
Data Attribute Variant
JavaScript Applied Variant
applyFocusRing(document.getElementById("js-ring"), {
color: "var(--md-sys-color-secondary)",
ringSize: "3px",
offset: "2px",
radius: "10px",
});
States
Ring visibility follows keyboard vs pointer interaction mode.
Interactive Example
Adjust ring values at runtime.
Event log:
API
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
data-focus-ring |
boolean | false | Marks element for initialization. |
data-focus-ring-color |
string | --ds-focus-ring-color |
Ring color override. |
data-focus-ring-width |
string | --ds-focus-ring-width |
Ring width override. |
data-focus-ring-offset |
string | --ds-focus-ring-offset |
Ring offset override. |
data-focus-ring-radius |
string | --ds-focus-ring-radius |
Ring radius override. |
Events
| Event | Detail | Description |
|---|---|---|
| None | - | Utility does not emit custom events. |
Functions
| Function | Signature | Description |
|---|---|---|
applyFocusRing |
(target, options?) |
Attach focus ring behavior to one element. |
initFocusRings |
(root?) |
Initialize all [data-focus-ring] elements in a
root.
|
removeFocusRing |
(target) |
Detach listeners and remove classes for a target. |
CSS Parts
| Part | Description |
|---|---|
| None | No shadow parts are exposed by this utility. |
CSS Custom Properties
| Property | Description |
|---|---|
--ds-focus-ring-color |
Focus ring color token. |
--ds-focus-ring-width |
Focus ring thickness token. |
--ds-focus-ring-offset |
Gap between host edge and ring. |
--ds-focus-ring-radius |
Ring radius token. |
Accessibility
Keyboard Interaction
| Key | Context | Expected Result |
|---|---|---|
Tab / Shift+Tab |
Focusable element with ring | Shows configured focus ring on keyboard focus |
Enter / Space |
Focusable button/control | Activates control while preserving ring behavior |
Semantics
- Pointer input clears keyboard-intent ring visibility.
- Ring thickness and offset can be tuned for dense layouts.
- Focus ring complements, not replaces, semantic focus behavior.
Usage Guidelines
- When to use: Use for custom controls that need consistent, visible keyboard focus across themes.
- When not to use: Avoid hiding native focus without providing an equivalent visible replacement.
-
Composition: Keep ring contrast high and prefer
initFocusRings()for declarative setup. - Common mistakes: Applying a ring to non-focusable elements creates inconsistent keyboard behavior.