Command Palette

Search for a command to run...

Hectal
Back to the lesson: Topic 7.3 — Keyboard and Focus
HTML · Example 1 of 2

Which elements are focusable?

Surprise: the tabIndex property says 0 for every a and button, even a link without href and a disabled button, because the spec gives those elements a default of 0. Calling focus() and checking document.activeElement is the real test. The heading is focusable by script but skipped by Tab. Click in the preview and press Tab to walk the real order.

Every control must work with the keyboard alone: interactive elements are focusable in source order, tabindex 0 and -1 adjust that, a skip link jumps past repeated menus, and focus must always be visible.

Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.

Ready for more? This phase has 6 hands-on exercises with automatic checks.

Practice questions

Write the code in the editor, run it, then open the model answer to compare.

01

Write a page header with a skip link, a nav of three links and a main with an h1, plus the CSS that hides the skip link until it's focused.

02

Write CSS that shows a 3 px blue outline with a 2 px offset for keyboard focus on every element, without showing it after mouse clicks on buttons.

03

A product card is <div class="card" onclick="openProduct()">. Rewrite it so it works with the keyboard without adding JavaScript key handlers.

Explain it without notes

01

Which elements are focusable by default, and how does tabindex change that?

02

What is a skip link, why is it needed, and how do you hide it without breaking it?

03

Why is outline: none dangerous, and what should you do instead?

04

What is a keyboard trap? Give an example and how to avoid it.

Which elements are focusable?

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

link | focusable: true | tabIndex: 0
nohref | focusable: false | tabIndex: 0
btn | focusable: true | tabIndex: 0
off | focusable: false | tabIndex: 0
field | focusable: true | tabIndex: 0
plain | focusable: false | tabIndex: -1
zero | focusable: true | tabIndex: 0
heading | focusable: true | tabIndex: -1