CodeBlanks Logo Icon CodeBlanks

Tabs and accordion

HTML course · Expert · Lesson 10/39

Apply ARIA tabs and accordion patterns.

The tabs pattern: tablist, tab, tabpanel

A tabbed interface has three parts: role="tablist" wraps the tab labels, role="tab" is one tab, and role="tabpanel" is that tab's content. You link a tab to its panel with aria-controls and id.

Standard shape: <div role="tablist"><button role="tab" aria-selected="true" aria-controls="p1">General</button></div> followed by <div role="tabpanel" id="p1">...</div>. Arrow keys move between tabs; that is why tabindex is tuned accordingly.

aria-selected and aria-controls

If a tab is selected, write aria-selected="true"; otherwise "false". Only one tab is selected at a time. aria-controls carries the id of the panel the tab governs, so a screen reader can hop from tab to panel.

On the panel side, it is good practice to link the panel's label to the tab's text via aria-labelledby. Example: <div role="tabpanel" id="p1" aria-labelledby="t1"> and <button role="tab" id="t1" aria-controls="p1">. This two-way link completes accessibility.

The accordion pattern

An accordion is built from expandable header and content pairs. Each header is a <button> that carries aria-expanded for open/closed state and aria-controls for the content id it governs.

The content region is either a plain <div> or takes role="region". In <button aria-expanded="false" aria-controls="b1">Section 1</button>, the header governs a closed region. Several headers in one accordion may stay open at once; if only-one-open behaviour is wanted, JavaScript handles that.

Exercise Write a two-tab tablist

Add a <div role="tablist"> to body; inside it put two <button role="tab">. The first tab has id t1, aria-selected true, aria-controls p1 and the text General. The second tab has aria-selected false, aria-controls p2 and the text Details. Add a <div role="tabpanel" id="p1" aria-labelledby="t1"> to body with a <p> inside, its text General content.

Show example solution
<body>
  <div role="tablist">
    <button role="tab" id="t1" aria-selected="true" aria-controls="p1">General</button>
    <button role="tab" aria-selected="false" aria-controls="p2">Details</button>
  </div>
  <div role="tabpanel" id="p1" aria-labelledby="t1">
    <p>General content.</p>
  </div>
</body>

Test yourself

  1. Which role wraps a tab's content?

    • role="tab"
    • role="tablist"
    • role="heading"
    • role="tabpanel"
    Show answer

    role="tabpanel" — Correct. role="tabpanel" wraps the content region of a tab.

  2. Write the selected tab's value

    <button role="tab" aria-selected="____" aria-controls="panel-1">General</button>
    Show answer
    <button role="tab" aria-selected="true" aria-controls="panel-1">General</button>
  3. Match each role to its place

    role="tablist"
    Tab list container
    role="tab"
    Single tab
    role="tabpanel"
    Tab content
    aria-selected="true"
    Selected tab

All lessons in Expert