Nested Focusgroups

A nested focusgroup creates an independent navigation scope within an outer focusgroup. Each group has its own axis, wrapping, memory, and entry point. Each focusgroup is its own tab stop; arrows navigate within the active group.

Try it: Use to navigate the outer toolbar; the nested group counts as a single stop; arrows land on it as a whole. Press Tab to move focus inside the nested group; once inside, use arrows. Press Tab again to exit.
View source
<div focusgroup="toolbar" aria-label="Main toolbar"
     class="toolbar-horizontal">
    <button type="button">Save</button>
    <button type="button">Print</button>
    <div role="group" focusgroup="toolbar" tabindex="0" aria-label="Text formatting"
         class="nested-toolbar">
        <button type="button">Bold</button>
        <button type="button">Italic</button>
        <button type="button">Underline</button>
    </div>
    <button type="button">Close</button>
    <button type="button">Exit</button>
</div>

Opt-Out Segments with focusgroup="none"

Use focusgroup="none" to exclude a subtree's focusable descendants from arrow navigation while keeping them reachable via Tab.

Try it: Use to navigate through the toolbar. Notice that "Help" and "Shortcuts" are skipped by arrow keys but still reachable via Tab.
View source
<div focusgroup="toolbar"
     aria-label="Segmented toolbar" class="toolbar-horizontal">
    <button type="button">New</button>
    <button type="button">Open</button>
    <button type="button">Save</button>
    <span focusgroup="none">
        <button type="button" class="opted-out-button">Help</button>
        <button type="button" class="opted-out-button">Shortcuts</button>
    </span>
    <button type="button">Close</button>
    <button type="button">Exit</button>
</div>

Deep Descendants

Focusgroup items don't need to be direct children. The browser discovers focusable descendants at any depth (unless they are inside a nested focusgroup or focusgroup="none").

Try it: Use to navigate. Arrow navigation works even though buttons are deeply nested inside <div> and <span> wrappers.
View source
<div focusgroup="toolbar"
     aria-label="Nested wrappers" class="toolbar-horizontal">
    <div>
        <span><button type="button">Alpha</button></span>
        <span><button type="button">Beta</button></span>
        <span><button type="button">Gamma</button></span>
    </div>
</div>

CSS reading-flow Integration

When reading-flow: flex-visual is set, the browser uses the visual flex order for all focus navigation, including focusgroup arrow keys, rather than DOM source order.

Try it: Use to navigate. With reading-flow: flex-visual, arrow navigation follows the visual left-to-right order (C → B → A), not the DOM order (A → B → C).
View source
<div focusgroup="toolbar" aria-label="Visual order"
     class="reading-flow-toolbar">
    <button type="button">A (DOM first)</button>
    <button type="button">B (DOM second)</button>
    <button type="button">C (DOM third)</button>
</div>

Feature Detection

Check whether the browser supports focusgroup before relying on it. If unsupported, you can fall back to a JavaScript-based roving tabindex or show a notice.

View source
<script>
if ('focusgroup' in HTMLElement.prototype) {
    // focusgroup is supported - use it!
    console.log('focusgroup is supported');
} else {
    // Not supported - fall back to JS roving tabindex
    console.log('focusgroup is NOT supported');
}
</script>