Interactive targets must be at least 24 by 24 CSS pixels
Tiny quantity buttons, close icons, colour swatches and filter checkboxes are hard to hit for people with tremors or limited dexterity, and for anyone on a phone. They tap the wrong size, remove the wrong item or give up, which costs orders on mobile in particular.
- Rule id
- vs-target-size
- Source
- Validiscan check
- Impact
- Serious
- Fix tier
- AUTO
- on Shopify, Shopware, WooCommerce and Magento
- Status
- runs
What the check does
Measures links, buttons and form controls and flags targets smaller than 24x24 CSS pixels that do not meet the spacing exception (2.5.8). Links inside running text are excluded. Supersedes the axe rule target-size.
The check also measures summary elements and elements with roles such as checkbox, tab and option, so listbox color swatches count. Disabled, hidden and zero-size targets are skipped, as are skip links parked off the page. A control’s visible <label> adds to its measured box.
A target is small when its width or height is below 24 CSS px, with 0.25 px allowed for sub-pixel layout. A small target still passes when:
- a 24 px circle centered on it reaches neither another target’s box nor the circle of another small target outside running text;
- it is an inline element, or an
inline-blocklink, in a block that also holds text outside any target. A heading above a list of links does not count.
The check runs separately in each scanned viewport, by default desktop (1440 px) and mobile (390 px), so a target that shrinks only on phones is reported for mobile. It does not apply the equivalent, user agent control or essential exceptions; a person judges those.
How to fix it
Give icon buttons and small controls a hit area of at least 24x24 CSS pixels (44x44 is better on touch screens), for example with padding or min-width and min-height, without changing the visible icon. Where a target must stay small, keep at least 24 pixels between it and its neighbours.
WCAG success criteria
- 2.5.8 Target Size (Minimum), level AA
EN 301 549 clauses
| WCAG criterion | Version 3.2.1 | Version 4.1.1 |
|---|---|---|
| 2.5.8 | not a clause in this version | 9.2.5.8 |
Where a recipe fixes it
Shopify: recipe target-size-padding
Show the before and after (1)
assets/base.css.liquid Changes to assets/base.css.liquid: 10 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1866 | 1866 | } | |
| 1867 | 1867 | ||
| 1868 | 1868 | /* ----------------------------------------------------------------- motion */ | |
| 1869 | Added | ||
| 1870 | Added | /* validiscan:target-size-padding */ | |
| 1871 | Added | .header__icon--account, | |
| 1872 | Added | .header__icon--cart, | |
| 1873 | Added | .swatch--button, | |
| 1874 | Added | .quantity__button { | |
| 1875 | Added | min-width: 24px; | |
| 1876 | Added | min-height: 24px; | |
| 1877 | Added | } | |
| 1878 | Added | /* /validiscan:target-size-padding */ |
Shopware: recipe target-size-padding
Show the before and after (1)
Resources/app/storefront/src/scss/_variant-broken.scss Changes to Resources/app/storefront/src/scss/_variant-broken.scss: 6 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 10 | 10 | ||
| 11 | 11 | .header-actions-btn { | |
| 12 | 12 | width: 18px; | |
| 13 | Added | min-width: 24px; | |
| 13 | 14 | height: 18px; | |
| 14 | Removed | min-height: 0; | |
| 15 | Added | min-height: 24px; | |
| 15 | 16 | padding: 0; | |
| 16 | 17 | } | |
| 17 | 18 | ||
| 96 | 97 | /* 18 px colour swatches, 20 px quantity and remove buttons (vs-target-size). */ | |
| 97 | 98 | .product-detail-configurator-option-input { | |
| 98 | 99 | width: 18px; | |
| 100 | Added | min-width: 24px; | |
| 99 | 101 | height: 18px; | |
| 102 | Added | min-height: 24px; | |
| 100 | 103 | margin-right: 4px; | |
| 101 | 104 | } | |
| 102 | 105 | ||
| 103 | 106 | .quantity-selector-group .btn, | |
| 104 | 107 | .line-item-remove-button { | |
| 105 | 108 | width: 20px; | |
| 109 | Added | min-width: 24px; | |
| 106 | 110 | height: 20px; | |
| 107 | Removed | min-height: 0; | |
| 111 | Added | min-height: 24px; | |
| 108 | 112 | padding: 0; | |
| 109 | 113 | } | |
| 110 | 114 |
WooCommerce: recipe target-size-padding
Show the before and after (1)
assets/css/main.css Changes to assets/css/main.css: 4 added, 2 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 710 | 710 | /* VALIDISCAN-SEED vs-target-size: 18 x 18 px icon links, 4 px apart. */ | |
| 711 | 711 | .kb-social__link { | |
| 712 | 712 | display: inline-flex; | |
| 713 | Removed | width: 18px; | |
| 714 | Removed | height: 18px; | |
| 713 | Added | width: 24px; | |
| 714 | Added | height: 24px; | |
| 715 | 715 | color: var(--kb-ink); | |
| 716 | Added | align-items: center; | |
| 717 | Added | justify-content: center; | |
| 716 | 718 | } | |
| 717 | 719 | ||
| 718 | 720 | .site-info { |
assets/css/woocommerce.css Changes to assets/css/woocommerce.css: 4 added, 4 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 421 | 421 | ||
| 422 | 422 | /* VALIDISCAN-SEED vs-target-size: 18 x 18 px colour swatches, 4 px apart. */ | |
| 423 | 423 | .kb-swatch { | |
| 424 | Removed | width: 18px; | |
| 425 | Removed | height: 18px; | |
| 424 | Added | width: 24px; | |
| 425 | Added | height: 24px; | |
| 426 | 426 | padding: 0; | |
| 427 | 427 | border: 1px solid rgba(0, 0, 0, 0.2); | |
| 428 | 428 | border-radius: 50%; | |
| 489 | 489 | /* VALIDISCAN-SEED vs-target-size: 18 x 18 px quantity steppers glued to the input. */ | |
| 490 | 490 | .kb-qty-minus, | |
| 491 | 491 | .kb-qty-plus { | |
| 492 | Removed | width: 18px; | |
| 493 | Removed | height: 18px; | |
| 492 | Added | width: 24px; | |
| 493 | Added | height: 24px; | |
| 494 | 494 | padding: 0; | |
| 495 | 495 | border: 1px solid #b9b3aa; | |
| 496 | 496 | border-radius: 2px; |
Magento: recipe target-size-padding
Show the before and after (1)
app/design/frontend/Validiscan/fixture/web/css/source/_theme.less Changes to app/design/frontend/Validiscan/fixture/web/css/source/_theme.less: 9 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1264 | 1264 | height: 18px; | |
| 1265 | 1265 | stroke-width: 3; | |
| 1266 | 1266 | } | |
| 1267 | Added | ||
| 1268 | Added | /* validiscan:target-size-padding */ | |
| 1269 | Added | .social-link, | |
| 1270 | Added | .actions-secondary .action, | |
| 1271 | Added | .qty-step { | |
| 1272 | Added | min-width: 24px; | |
| 1273 | Added | min-height: 24px; | |
| 1274 | Added | } | |
| 1275 | Added | /* /validiscan:target-size-padding */ |
app/design/frontend/Validiscan/fixture/web/css/styles-m.css Changes to app/design/frontend/Validiscan/fixture/web/css/styles-m.css: 9 added, 0 removed
| Line before | Line after | Change | Code |
|---|---|---|---|
| 1232 | 1232 | height: 18px; | |
| 1233 | 1233 | stroke-width: 3; | |
| 1234 | 1234 | } | |
| 1235 | Added | ||
| 1236 | Added | /* validiscan:target-size-padding */ | |
| 1237 | Added | .social-link, | |
| 1238 | Added | .actions-secondary .action, | |
| 1239 | Added | .qty-step { | |
| 1240 | Added | min-width: 24px; | |
| 1241 | Added | min-height: 24px; | |
| 1242 | Added | } | |
| 1243 | Added | /* /validiscan:target-size-padding */ |
Start with a free check of your shop.
Send your shop’s address. Validiscan scans it and replies with every failure the scan can prove, with the page and the code.
Request a free checkOr write to info@validiscan.com.
What the free check covers, and what it leaves out- You send
- your shop’s address
- Pages scanned
- up to 15
- You get
- every failure the scan can prove, with the page and the code
- On your shop
- public pages only; no login, nothing bought, no forms sent
- What it is not
- a full audit