Keyboard Navigation
⌨️ Keyboard Navigation
Tab Order Follows DOM Source Order
The default tab order follows DOM source order, not visual or CSS position. Flexbox order, absolute positioning, or grid placement can visually reposition an element without changing where it sits in the tab sequence — creating a confusing mismatch between what a keyboard user sees and where focus actually jumps.
tabindex Value | Effect |
|---|---|
0 | Adds the element to the natural tab order, at its actual DOM position |
-1 | Removes it from the tab order, but keeps it programmatically focusable via JS |
Positive (1, 2...) | Explicitly reorders the tab sequence — almost always an anti-pattern; avoid |
👁️ Focus Visibility
Browsers historically applied :focus styling to both keyboard and mouse interaction — leading many sites to strip it entirely with outline: none to "clean up" the look for mouse users. :focus-visible is the correct modern fix: it shows a focus indicator specifically for keyboard navigation, without applying it on a mouse click.
Removing Focus vs Styling It Correctly
outline: none
Clean for mouse users — and catastrophic for keyboard users, who now have zero visual indication of where focus currently is.
:focus-visible
Keyboard users get a clear focus indicator; mouse users never see it — the actual correct fix, not a removal.
Skip Links
A "Skip to Main Content" Link
A skip link is the very first focusable element on the page, letting keyboard users bypass repeated navigation without tabbing through it every single page. It's the keyboard-only user's equivalent of Chapter 2's landmark shortcut — someone who doesn't use a screen reader and can't jump by landmark experiences the exact same "re-tabbing through nav every time" problem otherwise.
🪟 Focus Management in Modals
A correct modal does three things, and missing any one creates a genuinely disorienting experience:
1. Move Focus In
On open, focus moves to the first focusable element or the modal's own heading — not left sitting on whatever triggered it.
2. Trap Focus
Tab and Shift+Tab cycle only among the modal's own focusable elements while it's open — never escaping to the (hidden) page behind it.
3. Restore Focus
On close, focus returns to whatever element originally opened the modal — never left "lost," resetting to the top of the document.
Custom Interactive Components Need Full Keyboard Support
Reinforcing Chapter 3's tablist example: a custom dropdown, combobox, or tabs component built without native elements needs someone to deliberately implement Tab, Enter, Space, Arrow keys, and Escape — matching whatever the ARIA Authoring Practices pattern specifies for that component. Chapter 8 builds several of these fully.
💻 Coding Challenges
Challenge 1: Diagnose a Tab-Order Mismatch
A form's fields are visually ordered Name, Email, Phone using CSS Grid with explicit order values, but the underlying HTML source order is Phone, Name, Email. Explain what a keyboard user experiences, and the fix.
Goal: Practice recognizing the DOM-order-vs-visual-order mismatch concretely.
Challenge 2: Write a Skip Link
Write the HTML and CSS for a skip link that's invisible until focused, jumps to a <main id="content"> element, and appears in the top-left corner when focused.
Goal: Practice implementing the visually-hidden-until-focused pattern correctly.
Challenge 3: Identify a Missing Modal Step
A modal correctly moves focus in on open and traps focus while open, but on close, focus simply disappears (nothing is focused at all). Identify which of the three steps is missing and explain the user impact.
Goal: Practice diagnosing a partial, incomplete focus-management implementation.
outline: none With No ReplacementThis is one of the single most common and most damaging accessibility mistakes on the web — removing the default focus outline purely for visual cleanliness, with nothing put in its place. It takes an otherwise perfectly keyboard-operable page and makes it completely unusable for keyboard users, who now have no way to see where they currently are as they tab through it. The fix is never to remove focus styling — it's to replace it correctly with :focus-visible, exactly as this chapter's earlier section describes. If a codebase has outline: none anywhere without an accompanying focus style, that's a real, high-priority bug, not a minor visual nitpick.
🎯 What's Next
With navigation and focus covered, the next chapter turns to one of the most common places accessibility breaks down in practice: Forms & Accessible Error Handling — label association, accessible error messages, and the placeholder-as-label anti-pattern.