Touch Target Size | Blue Frog Docs

Touch Target Size

Diagnose and fix interactive elements that are too small for touch and motor accessibility

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

  1. Open Chrome DevTools (F12)
  2. Click device toggle (Ctrl+Shift+M or mobile icon)
  3. Select a mobile device (iPhone, Pixel, etc.)
  4. Navigate your page
  5. 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:

  1. Right-click element → Inspect
  2. In Styles panel, check computed dimensions
  3. Look for width/height in Computed tab
  4. Should be minimum 24×24px (Level AA) or 44×44px (Level AAA)

Method 2: Lighthouse Mobile Audit

  1. Open Chrome DevTools (F12)
  2. Navigate to Lighthouse tab
  3. Select "Mobile" device
  4. Check "Accessibility"
  5. Click "Generate report"
  6. 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:

  1. Open your website on a smartphone or tablet

  2. 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
  3. 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:

  1. WAVE Extension:

    • Shows all interactive elements
    • Helps visualize tap target spacing
    • Flags very small elements
  2. axe DevTools:

    • Scans for target size issues
    • Identifies overlapping targets
    • Provides specific recommendations
  3. 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

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;
}

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

  1. Using default form controls - Too small on mobile
  2. Icon-only buttons without padding - Visual icon is 20px, no padding
  3. Close buttons (×) too small - Common on modals
  4. Checkbox/radio inputs - Default browser size is inadequate
  5. Social media icons - Often 24×24px or smaller
  6. Table action buttons - Edit/delete icons too small
  7. Pagination links - Numbers too close together
  8. Tag/chip close buttons - X icons too small
  9. Breadcrumb separators as links - Accidental taps
  10. 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:

  1. Test on mobile device:

    • Navigate site on actual phone/tablet
    • Tap all interactive elements
    • Verify comfortable, accurate tapping
    • No accidental mis-taps
  2. Run Lighthouse audit:

    • Select "Mobile" device
    • Generate accessibility report
    • Verify "Tap targets are sized appropriately" passes
    • Check no flagged elements remain
  3. Use touch target script:

    • Run the analysis script provided above
    • Verify no elements below 44×44px
    • Check spacing between adjacent targets
  4. Screen reader testing:

    • Verify targets are still accessible
    • Check aria-labels are present for icon buttons
    • Ensure focus indicators are visible
  5. 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:

Platform Troubleshooting Guide
Shopify Shopify Touch Target Guide
WordPress WordPress Touch Target Guide
Wix Wix Touch Target Guide
Squarespace Squarespace Touch Target Guide
Webflow Webflow Touch Target Guide

Additional Resources

// SYS.FOOTER