Testing target size

This page pairs with the "Highlight target size" bookmarklet, covering WCAG 2.2 2.5.8 Target Size (Minimum). The bookmarklet flags pointer targets smaller than 24 × 24 CSS pixels, draws a dashed 24px circle centred on each undersized target, and reports whether that circle overlaps another target.

What the bookmarklet reports:

Colour Meaning
No badgeMeets 24 × 24, or excluded from measurement entirely
AmberUnder 24 × 24, spacing is clear
RedUnder 24 × 24, its 24px circle overlaps another target

This is a warnings-only tool. 2.5.8 has exceptions that need human judgement, an inline text link, the same function available another way, or a control whose size the browser sets and the author never touched, and the bookmarklet can't evaluate any of those on its own. Where a warning might be one of these exceptions, the badge says so, it doesn't resolve it for you.

Example 1: passes

A button comfortably over 24 × 24.

Expected result: no badge at all. A genuine pass is silent, the summary panel at the bottom of the page is what confirms this target was actually measured and counted, not skipped.

HTML markup
<button style="width: 44px; height: 44px;">×</button>

Example 2: too small, spacing clear

A 16 × 16 button with plenty of space around it, nothing else nearby to conflict with.

Expected result: amber. Undersized, but its 24px circle doesn't overlap any other target, "16 × 16 — under 24 × 24. Spacing clear".

HTML markup
<button style="width: 16px; height: 16px;" aria-label="Close">×</button>

Example 3: too small, and too close together

Two 16 × 16 buttons with only 4px between them, close enough that their 24px circles overlap.

Expected result: red, on both buttons. Each is undersized, and each one's 24px circle overlaps the other, "24px circle overlaps 1 other target".

HTML markup
<button style="width: 16px; height: 16px;" aria-label="Decrease quantity">−</button>
<button style="width: 16px; height: 16px;" aria-label="Increase quantity">+</button>
<!-- 4px gap between them -->

Example 4: disabled, excluded entirely

The same tiny button as Example 2, but disabled.

Expected result: no badge, and not counted in the summary panel's total either. A disabled control can't receive a pointer action, so it isn't a target at all, this isn't a pass, it's an exclusion.

HTML markup
<button style="width: 16px; height: 16px;" aria-label="Close" disabled>×</button>

Example 5: hidden, excluded entirely

Nothing to see here, deliberately. A hidden field and a button removed from rendering, both excluded from measurement before size is even considered.

Expected result: no badge, no entry in the summary panel's total, for either element. Correct, not a bug in this page, an <input type="hidden"> has no visible interface at all, and a display: none element has no box to measure.

HTML markup
<input type="hidden" name="tracking-id" value="abc123">
<button style="display: none;">Never shown</button>

Example 6: inline text link

A link sitting inside a sentence, smaller than 24 × 24 because of its reduced font size.

For more information, read our full policy before continuing.

Expected result: still flagged, the tool doesn't grant the exception itself, but the badge text adds "Inline text link, exception may apply", flagging that this is exactly the kind of case 2.5.8 excludes, a link that's part of running text, and needs a human decision rather than an automated one.

HTML markup
<p>For more information, read our
  <a href="#" style="font-size: 12px;">full policy</a>
  before continuing.
</p>

Example 7: native control, unlabelled

A plain checkbox at its native size, no label anywhere nearby.

Expected result: flagged, with "Native control, check whether the author changed its size" appended. This is a nudge, not a verdict, a native checkbox rendered at its own default size is a common, often accepted exception, but this one has no visible label to union with either, so it's worth a second look regardless.

HTML markup
<input type="checkbox" style="width: 14px; height: 14px;" aria-label="Subscribe to updates">

Example 8: small control, rescued by its label

The same tiny checkbox, but with a real, adjacent <label>. Clicking the label activates the checkbox, so the label is part of the target, and here it's big enough on its own to carry the combined box over 24 × 24 in both directions.

Expected result: no badge. The checkbox alone is 14 × 14, but unioned with its label's padded box, the combined target clears 24 × 24 in both width and height, so it isn't undersized at all.

HTML markup
<input type="checkbox" id="rescued-checkbox" style="width: 14px; height: 14px;">
<label for="rescued-checkbox" style="padding: 8px 4px;">Subscribe to updates</label>

Example 9: small control, label too far away

The same pairing again, but with 60px between the checkbox and its label, well past the 12px gap the bookmarklet allows before it stops treating them as adjacent.

Expected result: flagged on its own, at 14 × 14. The label is still programmatically associated and still activates the checkbox when clicked, but it's positioned too far away to be counted as part of the same visual target, so the union doesn't apply and the checkbox is measured alone.

HTML markup
<div style="display: flex; gap: 60px;">
  <input type="checkbox" id="far-checkbox" style="width: 14px; height: 14px;">
  <label for="far-checkbox">Subscribe to updates</label>
</div>

Example 10: nested targets don't conflict with each other

A large clickable card, made interactive with role="button" and a click handler rather than a real <a> or <button>, specifically so it can validly contain a real nested <button> for a single action inside it.

Wireless keyboard

Expected result: the card itself passes silently, comfortably over 24 × 24. The icon button is undersized at 16 × 16, and its 24px circle does overlap the card underneath it, but since the card contains the button, that overlap isn't counted as a spacing conflict. Amber, not red, "Spacing clear".

HTML markup
<div role="button" tabindex="0" onclick="...">
  <p>Wireless keyboard</p>
  <button style="width: 16px; height: 16px;" aria-label="Add to favourites" onclick="event.stopPropagation()">
    ♥
  </button>
</div>

Example 11: hit area extended by ::before

A 16 × 16 button, but with a ::before overlay extending 8px past every edge, giving it a real, clickable hit area of roughly 32 × 32. Clicking anywhere in that overlay still activates the button, generated content is part of the element's own hit-testing.

Expected result: flagged as undersized, 16 × 16, even though the real clickable area is closer to 32 × 32. This is a documented, genuine limitation, not a bug, the bookmarklet measures getBoundingClientRect() on the element itself, and a ::before or ::after overlay isn't part of that measurement. Worth checking by hand before treating this one as a real failure.

HTML markup
<button style="width: 16px; height: 16px;" aria-label="Info">i</button>

/* extends the clickable area, but not the measured box */
button::before {
  content: '';
  position: absolute;
  inset: -8px;
}