0Pricing
Web Accessibility Academy · Lesson

Managing roving tabindex in Widgets

Let arrow keys move within a composite control.

Managing roving tabindex in Widgets is a free Web Accessibility Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Web Accessibility Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

One Stop for a Whole Widget

In a toolbar or radio group, Tab should reach the widget once, not every item. Roving tabindex is the pattern that makes this work.

The Core Idea

Exactly one item holds tabindex="0" at a time. Every other item gets tabindex="-1", so Tab enters the group at a single point.

Initial Setup

On load, give the first or selected item tabindex="0" and set the rest to tabindex="-1". That is the resting state of the group.

<button tabindex="0">Bold</button>
<button tabindex="-1">Italic</button>

Arrow Keys Move Within

Once focus is inside, the user moves between items with the arrow keys, not Tab. Tab still exits the whole widget.

The Roving Step

On an arrow press you do two things: set the old item to -1 and the new item to 0, then call focus() on the new one. 🧭

old.tabIndex = -1;
next.tabIndex = 0;
next.focus();

Why Only One Zero

Keeping a single tabindex="0" means Tab always lands on the item the user last used, so returning to the widget feels natural.

Match the APG Pattern

The ARIA Authoring Practices Guide specifies the exact keys for each widget. Follow its keyboard map rather than inventing one.

Optional Wrapping

Many widgets wrap arrow movement: pressing right on the last item loops to the first. Check the APG for whether your pattern should wrap.

Home and End Too

Composite widgets often add Home and End to jump to the first and last items, a small touch that speeds up navigation.

Roving vs aria-activedescendant

Roving tabindex moves real DOM focus. The alternative, aria-activedescendant, keeps focus on a container and points to a virtual active item.

Test the Whole Cycle

Tab in, arrow through every item, Tab back out, then Tab in again and confirm focus returns to the last-used item.

Quick Check

In a roving tabindex toolbar, how many items have tabindex="0" at any moment?

Recap

You mastered roving tabindex: one item at 0, the rest at -1, arrow keys rove the 0 between them, and Tab moves past the whole widget. 🚀

Frequently asked questions

Is the “Managing roving tabindex in Widgets” lesson free?

Yes — the full text of “Managing roving tabindex in Widgets” is free to read here on the web, and the Web Accessibility Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Web Accessibility Academy course, upgrade to CoddyKit PRO.

What will I learn in “Managing roving tabindex in Widgets”?

Let arrow keys move within a composite control. You practise Web Accessibility Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Web Accessibility Academy?

No prior experience is required. Web Accessibility Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Managing roving tabindex in Widgets” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Web Accessibility Academy lesson?

Yes. Every Web Accessibility Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. tabindex 0, -1, and Never Positive
  2. Moving Focus After an Action
  3. Returning Focus When a Layer Closes
  4. Managing roving tabindex in Widgets
← Back to Web Accessibility Academy