Web basics · Hard · 25 min

Accessible tabs with ARIA and the keyboard

Three buttons and three panels are not a tab widget until the ARIA roles say so and the arrow keys work.

Turn the preview markup into accessible tabs:

- #tabs gets role="tablist"; each button gets role="tab" and aria-controls with its panel's id (tab-models controls panel-models, and so on). - Each panel gets role="tabpanel" and aria-labelledby with its tab's id. - The active tab has aria-selected="true" and tabindex="0"; the others aria-selected="false" and tabindex="-1". Only the active panel is visible: hide the rest with hidden. - At the start Models is active. A click activates a tab. With focus on a tab, ArrowRight and ArrowLeft activate and focus the next or previous one, wrapping around at the ends.

Challenges 0/5

  • ARIA roles and relationships in place
  • Starts on Models: selected, focusable and its panel visible
  • Clicking Logs activates it and shows only its panel
  • ArrowRight moves to the next tab and wraps at the end
  • ArrowLeft from the first tab goes to the last

const tabs = [...document.querySelectorAll('#tabs button')];

function select(tab) {
  // set aria-selected and tabindex on every tab
  // show only the panel named in tab's aria-controls
}

// roles, aria-controls, aria-labelledby
// click and ArrowRight / ArrowLeft handlers
select(tabs[0]);
Console output appears here (console.log).

Go deeper: the W3C WAI reference →

This in production, with your data? Let's talk for 15 minutes →