Touch Target Size
What This Means
Touch target size refers to the minimum dimensions of interactive elements (buttons, links, form fields) that users can easily tap or click. Small touch targets create accessibility barriers for people with motor disabilities, vision impairments, or anyone using a mobile device. WCAG recommends a minimum target size of 44×44 pixels.
Impact on Your Business
Legal Compliance:
- Required by WCAG 2.1 Level AAA (Success Criterion 2.5.5 Target Size - 44×44 pixels)
- WCAG 2.2 Level AA (Success Criterion 2.5.8 Target Size Minimum - 24×24 pixels)
- Essential for mobile accessibility compliance
- Common finding in accessibility audits
User Experience:
- Users with motor disabilities struggle with small targets
- Older adults have difficulty with precise tapping
- 15% of mobile users have motor impairments affecting touch accuracy
- Small targets lead to mis-taps, frustration, and abandonment
- 53% of mobile visits are abandoned if page is difficult to use
Mobile Usability:
- 60% of web traffic comes from mobile devices
- Small buttons frustrate all mobile users, not just those with disabilities
- Average adult finger pad is 10-14mm (approximately 40-56 pixels)
- Adequate spacing prevents accidental taps
Conversion Impact:
- Frustrating tap targets reduce conversion rates
- Users give up on complex interactions
- Better touch targets improve form completion
- Larger buttons increase click-through rates
How to Diagnose
Method 1: Chrome DevTools Mobile Simulation
- Open Chrome DevTools (F12)
- Click device toggle (Ctrl+Shift+M or mobile icon)
- Select a mobile device (iPhone, Pixel, etc.)
- Navigate your page
- Try tapping buttons, links, and form fields
What to look for:
- Difficulty tapping small elements
- Accidentally tapping wrong element
- Need to zoom in to tap accurately
- Elements too close together
Measure target sizes:
- Right-click element → Inspect
- In Styles panel, check computed dimensions
- Look for width/height in Computed tab
- Should be minimum 24×24px (Level AA) or 44×44px (Level AAA)
Method 2: Lighthouse Mobile Audit
- Open Chrome DevTools (F12)
- Navigate to Lighthouse tab
- Select "Mobile" device
- Check "Accessibility"
- Click "Generate report"
- Look for:
- "Tap targets are not sized appropriately"
- Specific elements flagged
- Recommended fixes
What to look for:
- Failed tap target audits
- List of undersized elements
- Overlapping interactive elements
- Recommended minimum sizes
Method 3: Manual Touch Testing
On actual mobile device:
Open your website on a smartphone or tablet
Try to tap all interactive elements:
- Navigation links
- Buttons
- Form inputs
- Checkboxes/radio buttons
- Close buttons on modals
- Hamburger menus
- Social media icons
- Accordion toggles
Note difficulties:
- Elements you have to tap multiple times
- Accidentally tapping wrong element
- Need to zoom in to tap
- Frustration with precise tapping
What to look for:
- Icons without sufficient padding
- Close buttons (×) that are too small
- Checkbox/radio inputs that are hard to tap
- Links in dense text with small target area
- Buttons that feel cramped
Method 4: Browser Extensions
Install accessibility testing extensions:
WAVE Extension:
- Shows all interactive elements
- Helps visualize tap target spacing
- Flags very small elements
axe DevTools:
- Scans for target size issues
- Identifies overlapping targets
- Provides specific recommendations
Google Accessibility Checker:
- Built into Chrome DevTools
- Identifies small touch targets
- Shows affected elements
Method 5: Visual Inspection with CSS
Add temporary CSS to visualize target sizes:
// Run in browser console to visualize all interactive elements
const style = document.createElement('style');
style.textContent = `
/* Highlight interactive elements */
a, button, input, select, textarea, [role="button"], [onclick] {
outline: 2px solid red !important;
outline-offset: 2px !important;
}
/* Show size warnings */
a, button, input, select, textarea, [role="button"], [onclick] {
position: relative;
}
`;
document.head.appendChild(style);
// Check and log undersized elements
const interactiveElements = document.querySelectorAll('a, button, input, select, textarea, [role="button"], [onclick]');
const minSize = 44; // WCAG AAA recommendation
interactiveElements.forEach(el => {
const rect = el.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
if (width < minSize || height < minSize) {
console.warn(`Small touch target (${Math.round(width)}×${Math.round(height)}px):`, el);
}
});
What to look for:
- Elements smaller than 44×44px (AAA) or 24×24px (AA)
- Clustered interactive elements
- Insufficient spacing between targets
Method 6: Automated Testing Script
// Comprehensive touch target analysis
function analyzeTouchTargets() {
const minSizeAA = 24; // WCAG 2.2 Level AA
const minSizeAAA = 44; // WCAG 2.1 Level AAA
const results = {
total: 0,
failAA: [],
failAAA: [],
tooClose: []
};
const interactive = document.querySelectorAll(
'a, button, input, select, textarea, [role="button"], [role="link"], [onclick], [tabindex="0"]'
);
interactive.forEach(el => {
const rect = el.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
results.total++;
// Check minimum size
if (width < minSizeAA || height < minSizeAA) {
results.failAA.push({
element: el,
size: `${Math.round(width)}×${Math.round(height)}px`,
text: el.textContent.trim().substring(0, 50)
});
} else if (width < minSizeAAA || height < minSizeAAA) {
results.failAAA.push({
element: el,
size: `${Math.round(width)}×${Math.round(height)}px`,
text: el.textContent.trim().substring(0, 50)
});
}
});
// Report results
console.log(`\n📊 Touch Target Analysis`);
console.log(`Total interactive elements: ${results.total}`);
console.log(`\n❌ Failing WCAG 2.2 AA (< 24×24px): ${results.failAA.length}`);
results.failAA.forEach(item => {
console.warn(` ${item.size} - "${item.text}"`, item.element);
});
console.log(`\n⚠️ Failing WCAG 2.1 AAA (< 44×44px): ${results.failAAA.length}`);
results.failAAA.forEach(item => {
console.log(` ${item.size} - "${item.text}"`, item.element);
});
return results;
}
// Run analysis
analyzeTouchTargets();
General Fixes
Fix 1: Increase Button and Link Sizes
Problem: Buttons too small
/* Bad - Small touch targets */
.button {
padding: 4px 8px;
font-size: 12px;
/* Results in ~20×30px button */
}
.icon-button {
width: 20px;
height: 20px;
}
Solution: Minimum 44×44px targets
/* Good - Accessible touch targets */
.button {
min-height: 44px;
min-width: 44px;
padding: 12px 24px;
font-size: 16px;
}
.icon-button {
min-width: 44px;
min-height: 44px;
padding: 12px;
}
/* For smaller visual icons, increase padding */
.icon-button svg {
width: 20px;
height: 20px;
}
HTML example:
<!-- Bad -->
<button class="close" aria-label="Close">×</button>
<!-- Good -->
<button class="close-button" aria-label="Close">
<span class="icon">×</span>
</button>
.close-button {
min-width: 44px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
cursor: pointer;
}
.close-button .icon {
font-size: 24px;
}
/* Increase touch area on hover/focus */
.close-button:hover,
.close-button:focus {
background: rgba(0, 0, 0, 0.1);
outline: 2px solid #0066cc;
outline-offset: 2px;
}
Fix 2: Add Adequate Padding to Links
Problem: Links with insufficient touch area
<!-- Bad - Tiny tap targets -->
<p>
Read more about <a href="/accessibility">accessibility</a>,
<a href="/seo">SEO</a>, and
<a href="/performance">performance</a>.
</p>
/* Bad - Default link styling, small targets */
a {
color: blue;
text-decoration: underline;
}
Solution: Increase padding for touch
/* Good - Sufficient tap area */
a {
color: #0066cc;
text-decoration: underline;
padding: 4px 2px; /* Increases tap area */
margin: 0 -2px; /* Prevents visual shift */
display: inline-block;
min-height: 24px; /* WCAG 2.2 AA minimum */
}
/* Even better for mobile */
@media (max-width: 768px) {
a {
padding: 8px 4px;
margin: 0 -4px;
min-height: 44px; /* AAA recommendation */
line-height: 1.5;
}
}
For navigation links:
<nav>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/services">Services</a>
<a href="/contact">Contact</a>
</nav>
nav a {
display: inline-block;
padding: 12px 16px;
min-height: 44px;
min-width: 44px;
text-align: center;
}
Fix 3: Increase Form Input Sizes
Problem: Small form inputs
<!-- Bad - Small inputs -->
<input type="text" class="small-input">
<input type="checkbox" id="agree">
<label for="agree">I agree</label>
/* Bad - Tiny form controls */
.small-input {
height: 24px;
padding: 4px;
}
input[type="checkbox"] {
/* Default browser size ~13×13px */
}
Solution: Larger, more tappable inputs
<!-- Good - Large touch targets -->
<input type="text" class="text-input" placeholder="Enter email">
<div class="checkbox-wrapper">
<input type="checkbox" id="agree" class="checkbox-input">
<label for="agree" class="checkbox-label">
I agree to the terms and conditions
</label>
</div>
/* Good - Accessible form controls */
.text-input {
min-height: 44px;
padding: 12px 16px;
font-size: 16px; /* Prevents zoom on iOS */
border: 2px solid #ccc;
border-radius: 4px;
}
.text-input:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
border-color: #0066cc;
}
/* Larger checkbox */
.checkbox-input {
width: 24px;
height: 24px;
margin: 0;
cursor: pointer;
}
.checkbox-wrapper {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 0;
min-height: 44px;
}
/* Make entire label tappable */
.checkbox-label {
cursor: pointer;
flex: 1;
padding: 8px 0;
}
Custom styled checkbox with large touch target:
<div class="custom-checkbox">
<input type="checkbox" id="newsletter" class="checkbox-input">
<label for="newsletter" class="checkbox-custom">
<span class="checkbox-box"></span>
<span class="checkbox-text">Subscribe to newsletter</span>
</label>
</div>
.custom-checkbox {
position: relative;
}
.checkbox-input {
position: absolute;
opacity: 0;
width: 44px;
height: 44px;
cursor: pointer;
}
.checkbox-custom {
display: flex;
align-items: center;
gap: 12px;
min-height: 44px;
cursor: pointer;
padding: 8px;
}
.checkbox-box {
width: 24px;
height: 24px;
border: 2px solid #333;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.checkbox-input:checked + .checkbox-custom .checkbox-box::after {
content: '✓';
color: white;
font-size: 18px;
}
.checkbox-input:checked + .checkbox-custom .checkbox-box {
background: #0066cc;
border-color: #0066cc;
}
.checkbox-input:focus + .checkbox-custom .checkbox-box {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
Fix 4: Add Spacing Between Adjacent Targets
Problem: Buttons too close together
<!-- Bad - No spacing -->
<div class="button-group">
<button>Cancel</button>
<button>Save</button>
<button>Delete</button>
</div>
/* Bad - Buttons touching */
.button-group button {
min-height: 44px;
padding: 12px 24px;
}
Solution: Add adequate spacing
<!-- Good - Proper spacing -->
<div class="button-group">
<button>Cancel</button>
<button>Save</button>
<button class="danger">Delete</button>
</div>
/* Good - 8px minimum spacing */
.button-group {
display: flex;
gap: 8px; /* CSS gap for modern browsers */
flex-wrap: wrap;
}
/* Fallback for older browsers */
.button-group button {
min-height: 44px;
min-width: 44px;
padding: 12px 24px;
margin: 4px; /* Alternative to gap */
}
/* Mobile: stack vertically with more space */
@media (max-width: 768px) {
.button-group {
flex-direction: column;
gap: 12px;
}
.button-group button {
width: 100%;
}
}
WCAG spacing requirements:
- Minimum 8px spacing between targets (recommended)
- Or targets separated by non-interactive content
- Or targets in a sentence can be closer if inline
Fix 5: Make Icon-Only Buttons Accessible
Problem: Small icon buttons
<!-- Bad - Tiny icon buttons -->
<button class="icon-btn">
<i class="icon-edit"></i>
</button>
<button class="icon-btn">
<i class="icon-delete"></i>
</button>
/* Bad - Too small */
.icon-btn {
padding: 4px;
border: none;
background: none;
}
.icon-edit,
.icon-delete {
width: 16px;
height: 16px;
}
Solution: Minimum 44×44px with padding
<!-- Good - Large touch targets with labels -->
<button class="icon-button" aria-label="Edit item">
<svg class="icon" aria-hidden="true">
<!-- Edit icon SVG -->
</svg>
</button>
<button class="icon-button" aria-label="Delete item">
<svg class="icon" aria-hidden="true">
<!-- Delete icon SVG -->
</svg>
</button>
/* Good - Adequate touch target */
.icon-button {
min-width: 44px;
min-height: 44px;
padding: 12px;
border: 1px solid #ccc;
background: white;
border-radius: 4px;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
}
.icon-button .icon {
width: 20px;
height: 20px;
pointer-events: none; /* Prevents icon from being target */
}
.icon-button:hover {
background: #f5f5f5;
}
.icon-button:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
/* Mobile: even larger targets */
@media (max-width: 768px) {
.icon-button {
min-width: 48px;
min-height: 48px;
padding: 14px;
}
}
Fix 6: Fix Mobile Navigation
Problem: Hamburger menu too small
<!-- Bad - Tiny hamburger -->
<button class="hamburger">☰</button>
/* Bad */
.hamburger {
font-size: 20px;
padding: 8px;
}
Solution: Proper mobile menu button
<!-- Good - Large, accessible menu button -->
<button
class="mobile-menu-toggle"
aria-label="Open navigation menu"
aria-expanded="false"
>
<span class="hamburger-icon">
<span></span>
<span></span>
<span></span>
</span>
</button>
/* Good - 48×48px mobile target */
.mobile-menu-toggle {
min-width: 48px;
min-height: 48px;
padding: 12px;
background: transparent;
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.hamburger-icon {
width: 24px;
height: 18px;
position: relative;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.hamburger-icon span {
display: block;
height: 2px;
background: #333;
border-radius: 2px;
}
.mobile-menu-toggle:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
Fix 7: Table and Card Actions
Problem: Small action buttons in tables/cards
<!-- Bad - Tiny action icons -->
<table>
<tr>
<td>Product Name</td>
<td>
<a href="/edit/1">✎</a>
<a href="/delete/1">×</a>
</td>
</tr>
</table>
Solution: Adequate button sizes
<!-- Good - Proper action buttons -->
<table>
<tr>
<td>Product Name</td>
<td class="actions">
<button class="action-btn" aria-label="Edit Product Name">
<svg class="icon" aria-hidden="true"><!-- Edit icon --></svg>
<span class="sr-only">Edit</span>
</button>
<button class="action-btn danger" aria-label="Delete Product Name">
<svg class="icon" aria-hidden="true"><!-- Delete icon --></svg>
<span class="sr-only">Delete</span>
</button>
</td>
</tr>
</table>
.actions {
display: flex;
gap: 8px;
}
.action-btn {
min-width: 44px;
min-height: 44px;
padding: 10px;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
}
.action-btn .icon {
width: 20px;
height: 20px;
}
.action-btn:hover {
background: #f5f5f5;
}
.action-btn:focus {
outline: 2px solid #0066cc;
outline-offset: 2px;
}
Common Mistakes
- Using default form controls - Too small on mobile
- Icon-only buttons without padding - Visual icon is 20px, no padding
- Close buttons (×) too small - Common on modals
- Checkbox/radio inputs - Default browser size is inadequate
- Social media icons - Often 24×24px or smaller
- Table action buttons - Edit/delete icons too small
- Pagination links - Numbers too close together
- Tag/chip close buttons - X icons too small
- Breadcrumb separators as links - Accidental taps
- Overlapping touch targets - Multiple elements in same space
Touch Target Size Reference
WCAG Standards:
- Level AAA (2.1): Minimum 44×44 CSS pixels
- Level AA (2.2): Minimum 24×24 CSS pixels
- Spacing: 8px between targets or non-interactive content
Platform Guidelines:
- Apple iOS: 44×44 points (44×44px on standard density)
- Android Material Design: 48×48 dp (≈48×48px)
- Microsoft: 34×26 px minimum (44×44px recommended)
Best practice: 44×44px minimum for all interactive elements
Verification
After increasing touch target sizes:
Test on mobile device:
- Navigate site on actual phone/tablet
- Tap all interactive elements
- Verify comfortable, accurate tapping
- No accidental mis-taps
Run Lighthouse audit:
- Select "Mobile" device
- Generate accessibility report
- Verify "Tap targets are sized appropriately" passes
- Check no flagged elements remain
Use touch target script:
- Run the analysis script provided above
- Verify no elements below 44×44px
- Check spacing between adjacent targets
Screen reader testing:
- Verify targets are still accessible
- Check aria-labels are present for icon buttons
- Ensure focus indicators are visible
Cross-device testing:
- Test on various screen sizes
- Check responsive breakpoints
- Verify mobile-specific adjustments work
Platform-Specific Guides
Detailed implementation instructions for your specific platform: