Target size: how big should clickable icons be?
What WCAG 2.5.8 and 2.5.5 require for target size, how the 24px spacing exception works, and how to size copy buttons, icon buttons and grid cells.
5 min read
The copy icon next to a wallet address is the textbook undersized target: a 14 or 16 pixel glyph, often sitting right against an explorer link icon of the same size. Someone with a tremor, someone using a phone one-handed on a train, or anyone with a large finger will hit the wrong one or miss both.
WCAG has two criteria about this, one at AA and one at AAA. This guide explains both, shows how the spacing exception really works, and gives concrete sizes for the icon buttons that crypto interfaces are full of.
The two criteria
| Criterion | Level | Minimum target | Exceptions |
|---|---|---|---|
| 2.5.8 Target Size (Minimum) | AA, new in WCAG 2.2 | 24 by 24 CSS pixels | Spacing, equivalent, inline, user agent control, essential |
| 2.5.5 Target Size (Enhanced) | AAA | 44 by 44 CSS pixels | Equivalent, inline, user agent control, essential |
The target is the area that responds to a pointer, not the visible glyph. A 16px icon inside a 24px button with transparent padding has a 24px target. That distinction is what makes these criteria easy to meet without changing how anything looks.
For comparison, platform guidance for native apps is larger still: Apple's Human Interface Guidelines recommend at least 44 by 44 points, and Material Design recommends 48 by 48 dp. If your dApp is used mostly on phones, 44px is a better working minimum than 24px, whatever level you claim.
The exceptions to 2.5.8, in practice
Spacing. An undersized target still passes if a 24px diameter circle centered on it doesn't intersect another target, and doesn't intersect the 24px circle of another undersized target. For a row of small icons, that means their centers are at least 24px apart. Two 16px icons with an 8px gap between them pass, since their centers are 24px apart. The same icons with a 4px gap don't: their centers are 20px apart, so the circles overlap. Each circle also extends 4px beyond its 16px icon, so nothing else clickable may come closer than that.
Equivalent. The same function is available through another control on the same page that does meet the size. A tiny copy icon in a dense table can rely on a full-size "Copy address" button in the account panel on that page. It has to be the same function, though, not a different route to it.
Inline. Links inside a sentence, such as "read the docs on slippage" in a paragraph, are limited by line height and are exempt.
User agent control. A native checkbox you haven't restyled is the browser's responsibility.
Essential. A particular presentation is essential or legally required. This is rare in product interfaces; don't lean on it.
Making small icons hit bigger
You almost never need to make the icon bigger. Make the button bigger.
The simplest approach gives every icon button a fixed box and centers the glyph:
.icon-button {
display: inline-grid;
place-items: center;
width: 32px;
height: 32px;
padding: 0;
border: 0;
border-radius: 8px;
background: transparent;
}
.icon-button svg {
width: 16px;
height: 16px;
}
When layout can't spare the space, extend the hit area beyond the visible box with a pseudo-element. Clicks on a pseudo-element go to its element, so this counts as part of the target:
.icon-button-compact {
position: relative;
width: 16px;
height: 16px;
}
.icon-button-compact::after {
content: '';
position: absolute;
inset: -4px;
}
That turns a 16px button into a 24px target. Two cautions: expanded areas must not overlap neighboring targets (whichever is on top wins the click), and an ancestor with overflow: hidden clips the extra area, for pointer input as well as for painting.
Copy buttons next to addresses
A typical address row has an address, a copy button and an explorer link:
<div class="address-row">
<span class="address">0x71C7…976F</span>
<button type="button" class="icon-button" aria-label="Copy address">
<svg aria-hidden="true" viewBox="0 0 16 16"><rect x="4" y="4" width="9" height="9" rx="1.5" fill="none" stroke="currentColor" /></svg>
</button>
<a class="icon-button" href="/address/0x71C7" aria-label="View on explorer">
<svg aria-hidden="true" viewBox="0 0 16 16"><path d="M6 3h7v7M13 3L4 12" fill="none" stroke="currentColor" /></svg>
</a>
</div>
With the 32px .icon-button above and a small gap, both targets are comfortable and the row stays compact. Each button needs a name because it has no visible text; icon-only buttons need names covers that half. Many products also make the truncated address itself a copy target, which is generous and fine as long as it's clear what clicking it does. Displaying wallet addresses goes into truncation and copy feedback.
Other places to check
Modal close buttons. A 12px "×" in the corner of a wallet connection modal is common. Put it in a 32 to 40px button, and keep it clear of the modal's edge on phones.
Watchlist stars in market tables. A 14px star at the start of each row is an undersized target with another target (the row link) right next to it. Give the star its own 24px or larger cell and don't let the row link overlap it.
Token chips. Rows of "popular tokens" in a selector usually work at 28 to 32px tall with 8px between them.
Sortable column headers. Make the whole header cell the button, not just the small arrow.
Carousel dots and pagination. 8px dots placed 12px apart fail. Space their centers 24px apart, or make the hit area larger than the dot.
Icon grids. Grid cells in an icon picker or library are usually 48 to 96px, far above the minimum. The risk there is a small secondary action inside each cell, such as a quick-download button on hover. That inner button needs a full 24 by 24 target of its own, because it sits inside another target and can't rely on the spacing exception. Sizing guidance for icons themselves, as opposed to their targets, is in sizing token icons in lists and tables.
Mobile web. Bottom navigation, network switchers and "Max" buttons inside amount fields get used with thumbs. Aim for 44px there; mobile wallet UI patterns has more on thumb-first layouts.
A quick audit
Paste this into the browser console to list interactive elements smaller than 24 by 24 pixels:
const selector = 'a[href], button, input, select, textarea, [role="button"], [tabindex]'
document.querySelectorAll(selector).forEach((el) => {
const { width, height } = el.getBoundingClientRect()
if (width > 0 && (width < 24 || height < 24)) {
console.log(`${Math.round(width)}×${Math.round(height)}`, el)
}
})
It measures element boxes, so it won't see pseudo-element hit areas, and inline links will show up even though they're exempt. Treat the output as a list to review, then check each candidate against the spacing rule. Repeat at phone width, where layouts tend to squeeze icons closer together.