DEV Community

Vishal Singh
Vishal Singh

Posted on

HTML focusgroup: Arrow-Key Navigation Without Roving Tabindex

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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.
}
Enter fullscreen mode Exit fullscreen mode

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

  1. Find a small existing toolbar with a tested fallback.
  2. Document its current keyboard behaviour.
  3. Add focusgroup behind feature detection.
  4. Keep state and selection logic separate from focus movement.
  5. Run the same automated and manual accessibility tests on both paths.
  6. 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)

Collapse
 
micaavigliano profile image
Mica

people, this attribute is just experimental. It does not work in all browsers.