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 case | Option | Reason |
|---|---|---|
| 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 modality | Mouse 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 });
});