v145 · DOM · Focus
Focus's focusVisible option
Chrome 145 adds a focusVisible boolean to the FocusOptions dictionary passed to element.focus(). When true, the browser always paints a focus ring and matches :focus-visible, regardless of input modality. When false, focus is applied silently — no ring shown. This gives JavaScript code explicit control over the focus ring that CSS alone cannot provide.
concepts
-
Focus Ring Control
Three buttons that programmatically focus a target element with
focusVisible: true,focusVisible: false, and the default (no option). See how the focus ring appears and whether:focus-visibleis matched in each case. -
Keyboard vs. Mouse Pattern
A common pattern: show the focus ring when focus was moved via keyboard, hide it when moved by click. Shows how
focusVisiblelets JavaScript correctly communicate intent to the browser's focus ring system. -
Menu Focus Trace
Custom keyboard menu that calls
focus({focusVisible: true})on arrow-key moves and the silent default on click-driven dismissal. Logs every focus call so you can see the difference. -
Accessible Modal
A modal dialog that opens via mouse click (
focusVisible: false) or keyboard shortcut (focusVisible: true). The focus ring appears precisely when expected — check the event log to see which option fired in each case.
why it shipped
The :focus-visible CSS pseudo-class was introduced to let browsers show the focus ring only for keyboard navigation — hiding it after mouse clicks. But JavaScript-triggered focus (element.focus()) has ambiguous intent: was it a keyboard shortcut handler? A screen reader interaction? A mouse click handler? Before Chrome 145, JavaScript had no way to signal which — the browser guessed based on recent input events, often getting it wrong. The focusVisible option in FocusOptions adds explicit intent: pass true to always show the ring (keyboard-intent), false to always suppress it (mouse-intent), or omit to let the browser guess as before.
the API
// Always show focus ring (keyboard intent)
element.focus({ focusVisible: true });
// Always suppress focus ring (mouse intent)
element.focus({ focusVisible: false });
// Default: browser guesses based on recent input modality
element.focus();
element.focus({ preventScroll: true }); // also no focusVisible
// CSS can still customise :focus-visible as normal
button:focus-visible {
outline: 3px solid cornflowerblue;
outline-offset: 2px;
}