luvv to helpDiscover the Best Free Online Tools
Topic 4 of 8

Focus States And Tab Order

Learn Focus States And Tab Order for free with explanations, exercises, and a quick test (for Data Visualization Engineer).

Published: December 28, 2025 | Updated: December 28, 2025

Why this matters

As a Data Visualization Engineer, you build interactive dashboards, filters, legends, and chart elements. Many users navigate only with a keyboard or assistive technologies. Clear focus states and a logical tab order ensure every control can be reached, understood, and operated without a mouse.

  • Stakeholder dashboards: Users must tab through filters and chart controls in a predictable order.
  • Interactive legends: Series toggle buttons need visible focus and correct sequence.
  • Modals/tooltips: Focus must move to the modal and back when closed, without trapping users.
  • Custom chart elements (SVG/Canvas): If focusable, they must announce purpose and support keyboard navigation.

Concept explained simply

Focus is the element that receives keyboard input. Tab order is the sequence elements receive focus when pressing Tab. Good accessibility means users can move through controls in a sensible order and always see where they are.

Mental model

Think of your page as a guided path. Each stop (focusable element) should appear in the same order a sighted user would read left to right, top to bottom. A highly visible focus ring acts like a flashlight highlighting the current stop.

Key terms (quick reference)
  • DOM order: The order elements appear in the HTML. This is the default Tab order.
  • tabindex: Attribute that changes focus behavior. 0 includes in Tab order; -1 programmatically focusable only; avoid values > 0.
  • :focus and :focus-visible: CSS states to style focus indicators; prefer :focus-visible for keyboard-focused styling.
  • Roving tabindex: Pattern for composite widgets where only one item has tabindex="0" and the rest -1, with arrow keys moving focus.

Practical rules and heuristics

  • Match visual and DOM order. Reorder the HTML, not the focus, whenever possible.
  • Never remove outlines globally. If you customize, ensure a strong, consistent focus ring (at least 3:1 contrast).
  • Use :focus-visible for elegant styling that appears on keyboard focus but not on mouse click.
  • Avoid tabindex > 0. Use natural DOM order; use tabindex="0" sparingly; -1 for programmatic focus.
  • Group related controls (e.g., legend items). Consider roving tabindex and arrow key navigation within the group.
  • When opening modals, move focus to a meaningful control inside (e.g., Close). Trap focus within the modal, and return focus to the trigger on close.
  • For custom SVG chart items: make them buttons (or links) only if interactive; provide labels via aria-label and ensure they are keyboard-operable.
  • Keep Tab stops meaningful. Don’t include decorative elements or duplicate controls in the Tab order.

Worked examples

Example 1: Accessible legend as real buttons with visible focus

Goal: Toggle series visibility with a clear Tab order and focus ring.

<div role="group" aria-label="Chart legend">
  <button type="button" class="legend-btn" aria-pressed="true">Revenue</button>
  <button type="button" class="legend-btn" aria-pressed="true">Cost</button>
  <button type="button" class="legend-btn" aria-pressed="false">Profit</button>
</div>
<style>
.legend-btn { border: 1px solid #bbb; padding: .25rem .5rem; background:#fff; }
.legend-btn:focus-visible { outline: 3px solid #004aad; outline-offset: 2px; }
.legend-btn[aria-pressed="true"] { background:#eef6ff; }
</style>

Why it works: Buttons are naturally focusable in DOM order; aria-pressed communicates toggle state; :focus-visible gives a strong indicator.

Example 2: Modal with correct focus behavior

Goal: Open details modal from a chart control, trap focus inside, restore on close.

<button id="open-details">View details</button>

<div id="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title" hidden>
  <h2 id="modal-title">Quarterly details</h2>
  <button id="close-modal">Close</button>
  <p>Content...</p>
</div>

<!-- Behavioral notes (no JS shown):
1) When opening, focus #close-modal (or the dialog heading if not interactive).
2) Keep Tab cycling inside dialog controls only.
3) On close, return focus to #open-details.
-->

Why it works: Predictable entry point, no escape to background, and focus restored to the trigger after closing.

Example 3: Navigating a set of bars with roving tabindex

Goal: Only one bar is in Tab order; arrow keys move between bars.

<div role="listbox" aria-label="Monthly bars">
  <div role="option" tabindex="0" aria-label="January: 120">â–®</div>
  <div role="option" tabindex="-1" aria-label="February: 140">â–®</div>
  <div role="option" tabindex="-1" aria-label="March: 90">â–®</div>
</div>
<!-- Behavioral notes (no JS shown):
- Left/Right arrow keys move tabindex="0" to adjacent option and call .focus() on it.
- Tab moves out of the listbox to the next major control.
-->

Why it works: Users can reach the group with one Tab, then arrow around items without bloating the Tab sequence.

Exercises

Exercise: Fix legend tab order and focus states

You inherit a legend built with spans and tabindex values that skip around visually. Refactor it so users can Tab through items logically and always see focus.

Broken markup to fix
<div class="legend">
  <span tabindex="3">Revenue</span>
  <span tabindex="1">Cost</span>
  <span tabindex="2">Profit</span>
</div>
<style>
span { outline: none; }
</style>

Requirements:

  • DOM order matches visual order: Revenue, Cost, Profit.
  • Use real interactive elements and no tabindex > 0.
  • Visible, high-contrast focus ring using :focus-visible.
  • Communicate toggle state.
  • [ ] Rebuild with buttons in the natural DOM order
  • [ ] Remove tabindex > 0 and outline: none
  • [ ] Add :focus-visible styles (3:1 contrast)
  • [ ] Use aria-pressed to announce toggle state

Common mistakes and how to self-check

  • Hiding focus outlines globally. Self-check: Press Tab repeatedly—can you always see the focused element?
  • Using tabindex > 0 to force order. Self-check: Remove tabindexes—does the natural DOM order still make sense?
  • Tabbing into dozens of tiny chart items. Self-check: Group items and use roving tabindex with arrow keys.
  • Unmanaged modals. Self-check: After opening a modal, Tab should never reach the background until it’s closed.
  • Focusable decorative elements. Self-check: Only interactive or informative elements should be in the Tab sequence.

Practical projects

  • Retrofit a dashboard: Make all filters, legends, and toggles keyboard-accessible with visible focus. Document the new tab order.
  • Chart details modal: Implement proper focus trap and restoration. Add a quick checklist users can test with Tab and Shift+Tab.
  • Roving tabindex widget: Build an arrow-key navigable bar group or legend with only one Tab stop.

Learning path

  1. Learn focus basics: DOM order, Tab, Shift+Tab, Space/Enter activation, :focus-visible.
  2. Style focus consistently: Create a reusable focus ring token and apply across dashboard components.
  3. Master patterns: Toggle buttons, menus, dialogs, and roving tabindex groups.
  4. Test with a keyboard: No mouse allowed. Verify every control and path including errors and modals.
  5. Screen reader spot-checks: Ensure labels, states (e.g., aria-pressed), and roles announce correctly.

Who this is for and prerequisites

Who this is for:

  • Data Visualization Engineers building interactive dashboards.
  • BI developers integrating charts with filters and controls.
  • Anyone who needs accessible keyboard navigation in complex UIs.

Prerequisites:

  • Basic HTML/CSS and semantic elements (button, form inputs).
  • Comfort styling states with CSS.
  • Optional: Familiarity with ARIA roles and labels.

Next steps

  • Apply these rules to one live dashboard component today.
  • Create a team checklist for focus and tab order; run it in code reviews.
  • Schedule a 10-minute weekly keyboard-only test session on your product.

Mini challenge

Pick any screen with at least five interactive elements. Without a mouse, navigate it using Tab/Shift+Tab and arrow keys. Note any confusing jumps or missing focus indicators. Fix at least one issue and retest.

Quick test

Take the quick test below to check your understanding. Available for everyone for free; only logged-in users will have their progress saved.

Practice Exercises

1 exercises to complete

Instructions

You inherit a legend built with spans and tabindex values that skip around visually. Refactor it so users can Tab through items logically and always see focus.

Broken markup to fix:

<div class="legend">
  <span tabindex="3">Revenue</span>
  <span tabindex="1">Cost</span>
  <span tabindex="2">Profit</span>
</div>
<style>
span { outline: none; }
</style>

Requirements:

  • DOM order matches visual order: Revenue, Cost, Profit.
  • Use real interactive elements and no tabindex > 0.
  • Visible, high-contrast focus ring using :focus-visible.
  • Communicate toggle state via aria-pressed.
Expected Output
Tab order: Revenue -> Cost -> Profit, each as a button with a visible 3:1 focus ring and correct aria-pressed state. No tabindex values greater than 0. No outline: none.

Focus States And Tab Order — Quick Test

Test your knowledge with 8 questions. Pass with 70% or higher.

8 questions70% to pass

Have questions about Focus States And Tab Order?

AI Assistant

Ask questions about this tool