Toolbars, tab lists, menus, and other composite widgets usually need two keyboard behaviours:
- one Tab stop for the entire widget
- arrow keys to move between items inside it
Today, developers normally implement that pattern with JavaScript and a “roving tabindex.” One item has tabindex="0", every peer has tabindex="-1", and keyboard handlers constantly move those values.
The proposed HTML focusgroup attribute moves much of that repeated work into the browser.
It is important to be precise about availability: focusgroup is still an evolving web-platform feature. Chrome announced it for developer feedback and later included it in Chrome 150, but you should verify your required browsers and keep a fallback before using it in production.
The roving tabindex problem
A simple toolbar often starts like this:
<div role="toolbar" aria-label="Formatting">
<button tabindex="0">Bold</button>
<button tabindex="-1">Italic</button>
<button tabindex="-1">Underline</button>
</div>
JavaScript must then listen for arrow keys, find the next enabled item, update tabindex values, and move focus.
A robust implementation also handles:
- right-to-left layouts
- vertical writing modes
- wrapping at the first and last items
- disabled or hidden controls
- dynamically inserted items
- restoring the last-focused item
- nested widgets
That is a lot of duplicated code for a common interaction pattern.
The focusgroup version
With the proposed attribute, the toolbar becomes:
<div focusgroup="toolbar wrap" aria-label="Formatting">
<button type="button">Bold</button>
<button type="button">Italic</button>
<button type="button">Underline</button>
</div>
The browser can provide arrow-key movement, one Tab stop, direction-aware navigation, and last-focused memory.
The wrap modifier lets navigation continue from the final item back to the first.
Navigation is not selection
Moving focus is only one part of many widgets.
In a tab list, arrow keys may move focus, but your application still needs to:
- update
aria-selected - show the selected panel
- hide other panels
- decide whether selection follows focus
- update the URL when deep linking is supported
focusgroup does not replace the business or state logic that makes a component work. It targets the repeated keyboard-navigation layer.
A tab-list example
<div focusgroup="tablist wrap nomemory" aria-label="Account sections">
<button
id="profile-tab"
aria-controls="profile-panel"
aria-selected="true"
focusgroupstart
>
Profile
</button>
<button
id="security-tab"
aria-controls="security-panel"
aria-selected="false"
>
Security
</button>
</div>
focusgroupstart marks the initial entry point. The nomemory modifier tells the browser not to restore the previously focused item when the user returns, which can be useful when focus should enter on the currently selected tab.
Application JavaScript still switches the panels and selected state.
Logical directions matter
The proposal uses logical directions instead of assuming every interface is horizontal and left-to-right.
An inline focus group usually responds to left and right arrows in an English layout. In another writing mode or direction, the browser can adapt the navigation to the document.
That behaviour is hard to reproduce correctly when every design system ships its own keyboard handler.
Feature detection and fallback
Do not remove your proven roving-tabindex implementation until your browser policy supports the new attribute.
if ("focusgroup" in HTMLElement.prototype) {
// Use the native focusgroup path.
} else {
// Initialize the existing roving-tabindex fallback.
}
Your HTML should retain meaningful labels and appropriate semantics in both paths.
Accessibility testing is still required
A browser primitive can reduce implementation mistakes, but it cannot decide whether you chose the correct widget pattern.
Test:
- Tab and Shift+Tab entry and exit
- every relevant arrow key
- Home and End if your pattern expects them
- disabled and dynamically removed items
- zoom and reflow
- right-to-left content
- screen readers in your supported browser combinations
- touch and pointer interaction
Also check for controls such as text inputs that use arrow keys internally. A keyboard user must always have a clear way to navigate and leave the component.
A safe migration plan
- Find a small existing toolbar with a tested fallback.
- Document its current keyboard behaviour.
- Add
focusgroupbehind feature detection. - Keep state and selection logic separate from focus movement.
- Run the same automated and manual accessibility tests on both paths.
- Expand only after browser support and real-world behaviour meet your policy.
Conclusion
focusgroup is promising because it turns a common accessibility pattern into a platform capability. It can reduce repeated JavaScript while giving the browser more responsibility for writing modes, memory, and focus order.
It is not a reason to stop thinking about semantics or testing. Use it as progressive enhancement, keep the current path, and let support evidence decide when the fallback can be retired.
Sources:
Top comments (1)
people, this attribute is just experimental. It does not work in all browsers.