Keyboard and focus Rule

Buttons and links must be big enough to press target-size

Every control you can click or tap needs to be at least 24 by 24 CSS pixels, or have enough empty space around it that a 24 pixel circle centred on it does not touch a neighbour. Smaller than that and people miss, or hit the control next door. Links inside a line of text are exempt, as are controls the browser draws itself.

Websight reports this as All touch targets must be 24px large, or leave sufficient space

Who it affects

Someone with Parkinson's checking the train timetable on their phone aims for the next hour arrow, which is 16 pixels wide, and hits previous hour instead. Twice.

Someone with large fingers on a small phone cannot tell which of three icons touching each other they have pressed until the page changes.

Someone using a head pointer or eye tracker has to hold the cursor still inside a target to click it. The smaller the target, the longer and harder that is.

Broken versus fixed

Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.

Broken

Three 16 pixel buttons with no gap between them. On a phone, one fingertip covers all three.

Fixed

32 pixel buttons with 8 pixels between them. Each one has room to be pressed on its own.

Show the markup behind both examples
Broken
<style>body{font-family:system-ui;margin:0;padding:12px}p{margin:0 0 8px}button{width:16px;height:16px;padding:0;border:1px solid #777;background:#fff;border-radius:3px;margin:0;vertical-align:middle}svg{width:10px;height:10px;display:block;margin:auto}</style>
<p>Departures: Oxford to Reading</p>
<button type="button" aria-label="Previous hour"><svg viewBox="0 0 10 10"><path d="M7 1 3 5l4 4" fill="none" stroke="#333" stroke-width="2"/></svg></button><button type="button" aria-label="Next hour"><svg viewBox="0 0 10 10"><path d="M3 1l4 4-4 4" fill="none" stroke="#333" stroke-width="2"/></svg></button><button type="button" aria-label="Refresh"><svg viewBox="0 0 10 10"><circle cx="5" cy="5" r="3.5" fill="none" stroke="#333" stroke-width="2"/></svg></button>
Fixed
<style>body{font-family:system-ui;margin:0;padding:12px}p{margin:0 0 8px}button{width:32px;height:32px;padding:0;border:1px solid #777;background:#fff;border-radius:4px;margin:0 8px 0 0;vertical-align:middle}svg{width:14px;height:14px;display:block;margin:auto}</style>
<p>Departures: Oxford to Reading</p>
<button type="button" aria-label="Previous hour"><svg viewBox="0 0 10 10"><path d="M7 1 3 5l4 4" fill="none" stroke="#333" stroke-width="2"/></svg></button><button type="button" aria-label="Next hour"><svg viewBox="0 0 10 10"><path d="M3 1l4 4-4 4" fill="none" stroke="#333" stroke-width="2"/></svg></button><button type="button" aria-label="Refresh"><svg viewBox="0 0 10 10"><circle cx="5" cy="5" r="3.5" fill="none" stroke="#333" stroke-width="2"/></svg></button>

Test it by hand in two minutes

  1. Open DevTools, press Ctrl+Shift+C (Cmd+Shift+C on a Mac) and hover each small button or icon. The tooltip shows its size; both numbers should be 24 or more.
  2. If a control is smaller, check the gap to its neighbours. Picture a 24 pixel circle around its centre: it must not overlap a neighbour or a neighbour's circle.
  3. Open the page on a phone and tap each icon in a row of icons with your thumb. Note any that trigger the wrong one.
  4. Skip links inside sentences; the rule does not apply to them. Do check pagination numbers, close buttons, star ratings, calendar days and table row actions.

The fix

Before
.icon-btn { width: 16px; height: 16px; }
After
.icon-btn { min-width: 24px; min-height: 24px; }

Make the button bigger, not the icon. Padding counts; the visible icon can stay small as long as the clickable box is 24 by 24 or more.

Controls that cannot grow

Before
.page-link { width: 18px; height: 18px; margin: 0; }
After
.page-link { width: 18px; height: 18px; margin: 0 8px; }

Spacing also satisfies the rule. With 18 pixel targets and 8 pixels between them, each one's 24 pixel zone is clear of the next.

Link that wraps a small icon

Before
<a href="/basket"><svg width="16" height="16" aria-label="Basket">...</svg></a>
After
<a href="/basket" class="icon-link"><svg width="16" height="16" aria-label="Basket">...</svg></a>
<style>.icon-link { display: inline-flex; padding: 4px; }</style>

An inline link is only as big as its content. display: inline-flex (or inline-block) lets padding grow the clickable area.

Common mistakes

  • Enlarging the icon image but leaving the button the same size.
  • Growing the target with a transparent border, then removing it on hover so the size jumps.
  • Reading the rule as 44 pixels and deciding it cannot be met; 24 is the AA minimum, 44 is the AAA target.
  • Shrinking a close button on mobile to save space, exactly where fingers are least precise.

WCAG criteria this rule maps to

axe-core tags this rule as WCAG 2.2 level AA. It is one of the checks for:

The scanner measures the rendered size of each clickable element and the gaps to its neighbours. It cannot judge the exceptions: whether a control is part of a sentence, whether an equally sized alternative exists elsewhere on the page, or whether the small size is essential. It also measures only what is on screen in the current viewport, so check at phone widths too. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.

Scan your own page for this and 63 other checks

Open any page in Chrome, click Websight, and get a score out of 100 with every issue explained and a draft fix snippet per element.

Add Websight to Chrome

Free scans, no account, nothing leaves your computer. Automated tools find only part of the problems; the extension says so on every report.