v145 · Web APIs · Accessibility · demo

Focus Ring Control

Four real-world scenarios showing when focusVisible: true, false, or the default heuristic is the right choice. Each scenario has trigger buttons to fire element.focus() with each option — watch the focus ring appear and disappear in the live stage.

Chrome 145: element.focus({ focusVisible: true | false }) gives JavaScript explicit control over the :focus-visible state. Use it when the browser heuristic picks the wrong outcome for your use case.

Click the colored trigger buttons to focus the target element with each option · observe the focus ring

Skip link — focus main content
Best option: focusVisible: false — skip link itself highlighted; main content should not show ring
Main content area
Click a button above to focus the card
✓ false: the skip link is already visually highlighted; adding a ring on main content is redundant and visually noisy. ✗ true: shows unnecessary ring when user clicked a link.
Keyboard shortcut opens search
Best option: focusVisible: true — user pressed a key, ring confirms keyboard context
Click a button above to focus the input
✓ true: keyboard shortcut (e.g. Ctrl+K) implies keyboard context; ring helps user know where they're typing. ✗ false: hides the ring — user may not realise the input has focus.
Programmatic scroll-to-section
Best option: focusVisible: false — section receives focus for anchor nav but ring is distracting
Section: Getting Started
Click a button above to focus the section heading
✓ false: focus is needed for screen readers to announce the section, but the visible ring distracts sighted users who clicked a link. ✗ true: ring appears on static content — looks broken.
Dialog close — restore focus to trigger
Best option: match how dialog was opened (use a stored flag)
Dialog is closed
Open the dialog, then close it with one of the options
✓ Match modality: track how the dialog was opened (e.detail === 0 for keyboard, > 0 for mouse). Use the same focusVisible when restoring. ✗ Always true/false: mismatches between keyboard and mouse users.
Use caseOptionReason
Skip link / anchor nav{ focusVisible: false }Focus for AT, but ring is visually distracting on non-interactive target
Keyboard shortcut{ focusVisible: true }User is in keyboard context — ring is expected and helpful
Dialog open (auto-focus first item){ focusVisible: true }Keyboard users need to know where focus landed
Dialog close (restore trigger)Match opening modalityMouse user: false; keyboard user: true
Scroll into view + focus{ focusVisible: false }Ring on static content is usually surprising/wrong
Default programmatic focus(no option)Let the browser heuristic decide — usually correct for simple cases
// Chrome 145: explicit focusVisible control
element.focus({ focusVisible: true });   // :focus-visible matches → ring shown
element.focus({ focusVisible: false });  // :focus-visible won't match → ring hidden
element.focus();                         // browser heuristic (default)

// Pattern: track how dialog was opened, restore with matching modality
let openedByKeyboard = false;

openBtn.addEventListener('click', e => {
  openedByKeyboard = e.detail === 0; // detail=0 → keyboard activation
  dialog.show();
  firstFocusable.focus({ focusVisible: true }); // always show ring inside dialog
});

dialog.addEventListener('close', () => {
  openBtn.focus({ focusVisible: openedByKeyboard });
});

see also