Accordion with Opt-Out Panels

Up/Down arrows navigate between accordion headers. Panel content is opted out of arrow navigation with focusgroup="none", but interactive elements inside panels remain reachable via Tab.

focusgroup="toolbar block"
Try it: Use to move between accordion headers. Click a header or press Enter/Space to expand/collapse. Press Tab to reach interactive content inside expanded panels.

The focusgroup attribute provides declarative arrow-key navigation for composite widgets. Try these documentation links and — they're still reachable via Tab, but arrow keys skip right over this panel.

View source
<div focusgroup="toolbar block" role="group"
     aria-label="Accordion sections">
    <h3>
        <button type="button" class="expanded" aria-expanded="true"
                aria-controls="acc-panel1">Section 1: Getting
                     Started</button>
    </h3>
    <div focusgroup="none" role="region" id="acc-panel1">
        <p>Panel content with <a href="#">links</a> and
        <input type="text" placeholder="inputs"> that remain
        tabbable but are skipped by arrow keys.</p>
    </div>

    <h3>
        <button type="button" aria-expanded="false"
                aria-controls="acc-panel2">Section 2:
                     Configuration</button>
    </h3>
    <div focusgroup="none" role="region" id="acc-panel2" hidden>
        <p>More panel content...</p>
    </div>

    <h3>
        <button type="button" aria-expanded="false"
                aria-controls="acc-panel3">Section 3: Advanced
                     Usage</button>
    </h3>
    <div focusgroup="none" role="region" id="acc-panel3" hidden>
        <p>Even more content...</p>
    </div>
</div>

Long Content: A Possible Mitigation

Because focusgroup arrow keys jump directly between headers, long panel content can be missed entirely. If a panel has more content than fits on screen, the user may never see it when arrowing through headers.

One possible mitigation: When a section is expanded, move focus into the panel. The panel is a focusable scrollable region (tabindex="0") with focusgroup="none", so arrow keys scroll its content instead of jumping to the next header. The user can press Tab to move back to the accordion headers when they're done reading. Other approaches — such as requiring an activation step before navigating away, showing a "skip to next section" link inside the panel, or avoiding focusgroup entirely for content-heavy accordions — may be more appropriate depending on the use case.

focusgroup="toolbar block"
Try it: Click a header or press Enter/Space to expand. Focus moves into the panel — use to scroll the long content. Press Tab to return to the accordion headers.

View source
<div focusgroup="toolbar block" role="group"
     aria-label="Articles">
    <h3>
        <button type="button" aria-expanded="false"
                aria-controls="long-panel1">The Focusgroup
                     Problem</button>
    </h3>
    <div focusgroup="none" role="region" tabindex="0"
         id="long-panel1" class="panel-scrollable" hidden
         aria-label="The Focusgroup Problem">
        <p>Long panel content goes here...</p>
    </div>
    <!-- more sections ... -->
</div>

<script>
// On expand, move focus into the panel so arrow keys scroll
accordion.querySelectorAll("h3 button").forEach(function (btn) {
    btn.addEventListener("click", function () {
        if (btn.getAttribute("aria-expanded") === "true") {
            var panel = document.getElementById(
                btn.getAttribute("aria-controls")
            );
            if (panel) panel.focus();
        }
    });
});
</script>

Key Point: focusgroup="none"

The none value opts an element and its subtree out of the ancestor focusgroup. This is crucial for composite widgets like accordions where: