In Ancient Egypt, the roads and corridors of temples were precisely planned so that every pilgrim could reach their destination. Similarly, websites must provide clear navigation paths for users who do not use a mouse - they navigate exclusively using the keyboard.
Many people use websites only with a keyboard:
| Key | Function | |:---|:---| |
Tab | Move to the next interactive element |
| Shift + Tab | Return to the previous element |
| Enter | Activate a link or button |
| Space | Activate a button, check a checkbox |
| Arrow keys | Navigate in menus, radio buttons, tablist |
| Escape | Close a dialog, cancel |HTML elements that are naturally focusable (you can Tab to them):
1<!-- These elements are naturally focusable -->
2<a href="/link">Link</a>
3<button>Button</button>
4<input type="text">
5<select>...</select>
6<textarea>...</textarea>
7
8<!-- These elements are NOT naturally focusable -->
9<div>Cannot Tab to this</div>
10<span>This neither</span>
11<p>And not this</p>tabindex controls whether and when an element receives focus:1<!-- tabindex="0" - element becomes focusable in natural order -->
2<div tabindex="0" role="button" onclick="handleClick()">
3 Click me
4</div>
5
6<!-- tabindex="-1" - focusable programmatically, but NOT via Tab -->
7<div tabindex="-1" id="error-message">
8 An error occurred!
9</div>
10
11<!-- tabindex="1+" - AVOID! Changes natural order -->
12<!-- This is an antipattern and causes navigation chaos -->
13<input tabindex="3" placeholder="Third">
14<input tabindex="1" placeholder="First">
15<input tabindex="2" placeholder="Second">Rule: Use only
tabindex="0" and tabindex="-1". Never use positive values!Skip links allow keyboard users to skip repetitive navigation and go directly to the main content:
1<!-- Skip link - first element on the page -->
2<a href="#main-content" class="skip-link">
3 Skip to main content
4</a>
5
6<header>
7 <nav>
8 <!-- Long navigation that the user can skip -->
9 <a href="/">Home</a>
10 <a href="/exhibitions">Exhibitions</a>
11 <a href="/tickets">Tickets</a>
12 <a href="/contact">Contact</a>
13 </nav>
14</header>
15
16<main id="main-content">
17 <h1>Welcome to the Egyptian Museum</h1>
18 <!-- ... -->
19</main>1/* Skip link visually hidden, but visible on focus */
2.skip-link {
3 position: absolute;
4 top: -40px;
5 left: 0;
6 background: #000;
7 color: #fff;
8 padding: 8px 16px;
9 z-index: 100;
10 transition: top 0.3s;
11}
12
13.skip-link:focus {
14 top: 0;
15}Never remove outline from focusable elements!
1/* BAD - hiding focus */
2*:focus {
3 outline: none; /* DO NOT DO THIS! */
4}
5
6/* GOOD - custom but visible focus */
7a:focus-visible,
8button:focus-visible {
9 outline: 3px solid #d4af37;
10 outline-offset: 2px;
11 border-radius: 2px;
12}The
:focus-visible pseudo-class is better than :focus because it shows the outline only during keyboard navigation, not on mouse click.When you open a modal, focus must be "trapped" inside it:
1<dialog id="ticket-dialog" aria-labelledby="dialog-title">
2 <h2 id="dialog-title">Buy a Ticket</h2>
3 <form>
4 <label for="quantity">Number of tickets:</label>
5 <input type="number" id="quantity" min="1" max="10" value="1">
6 <button type="submit">Buy</button>
7 <button type="button" onclick="closeDialog()">Cancel</button>
8 </form>
9</dialog>The
<dialog> element automatically manages focus - it traps Tab inside and restores focus after closing.1<nav aria-label="Main navigation">
2 <ul role="menubar">
3 <li role="none">
4 <a href="/" role="menuitem">Home</a>
5 </li>
6 <li role="none">
7 <a href="/exhibitions" role="menuitem"
8 aria-current="page">Exhibitions</a>
9 </li>
10 <li role="none">
11 <a href="/tickets" role="menuitem">Tickets</a>
12 </li>
13 </ul>
14</nav>The
aria-current="page" attribute informs the screen reader which page the user is currently on.Keyboard navigation is like clearly marked corridors in a pyramid - without them, even the most beautifully decorated chamber remains inaccessible to many visitors.