EthicsComputerCourses
Join training +91 90532 10052

Touch Targets & Pointer Input

Web Accessibility · Lesson 12 of 28 Beginner 7 min read Updated

Most Indians browse the web on phones. A tiny "x" button that is easy to hit with a mouse can be almost impossible to tap for someone with large fingers, a tremor, arthritis, or a phone in one hand on a moving bus. WCAG has a group of criteria about pointer input: mouse, touch, stylus and anything else that points.

In this lesson you will learn the WCAG 2.2 target size rules, make small icons easier to hit without changing how they look, and give drag and swipe actions a simple alternative.

Target size rules

A target is the area that responds to a click or tap. WCAG has two target size criteria:

CriterionLevelRequirement
2.5.8 Target Size (Minimum)AATargets are at least 24 by 24 CSS pixels, with exceptions
2.5.5 Target Size (Enhanced)AAATargets are at least 44 by 44 CSS pixels, with fewer exceptions

The level AA criterion has five exceptions:

  • Spacing: a smaller target passes if a 24 pixel circle centred on it does not overlap any other target or the circle of another small target. In other words, small targets need empty space around them.
  • Equivalent: the same action is available from another control that meets the size.
  • Inline: the target is a link inside a sentence or paragraph of text.
  • User agent control: the size is set by the browser and the author did not change it, such as a default checkbox.
  • Essential: a particular size or arrangement is essential, such as pins on a map that must be in exact places.

Phone platform guidelines go further: Apple recommends hit areas of at least 44 by 44 points and Android's Material Design recommends 48 by 48 density-independent pixels. Treat 24 pixels as the legal floor and 44 or more as the comfortable size for mobile.

Run this example. The script measures each button and shows its size.

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Target Sizes</title>
  <style>
    body { font: 16px/1.5 system-ui, sans-serif; }
    .row { display: flex; align-items: center; margin-bottom: 16px; }
    .icon { width: 18px; height: 18px; padding: 0; border: 1px solid #555; background: #eee; font-size: 12px; line-height: 1; }
    .tight .icon { margin: 0 1px; }
    .spaced .icon { margin: 0 6px; }
    .big .icon { width: auto; height: auto; min-width: 44px; min-height: 44px; margin: 0 4px; }
    output { margin-left: 12px; color: #444; }
  </style>
</head>
<body>
  <h1>Quantity: Masala dosa, ₹90</h1>

  <div class="row tight"><button class="icon" aria-label="Decrease">-</button><button class="icon" aria-label="Increase">+</button><output></output></div>
  <div class="row spaced"><button class="icon" aria-label="Decrease">-</button><button class="icon" aria-label="Increase">+</button><output></output></div>
  <div class="row big"><button class="icon" aria-label="Decrease">-</button><button class="icon" aria-label="Increase">+</button><output></output></div>

  <script>
    for (const row of document.querySelectorAll(".row")) {
      const [a, b] = row.querySelectorAll("button");
      const ra = a.getBoundingClientRect();
      const rb = b.getBoundingClientRect();
      const gap = rb.left - ra.right;
      const centres = (rb.left + rb.width / 2) - (ra.left + ra.width / 2);
      row.querySelector("output").textContent =
        `${Math.round(ra.width)} x ${Math.round(ra.height)} px, gap ${Math.round(gap)} px, centres ${Math.round(centres)} px apart` +
        (ra.width >= 24 && ra.height >= 24 ? ": passes by size" : centres >= 24 ? ": passes by spacing" : ": fails 2.5.8");
    }
  </script>
</body>
</html>

The first pair is tiny and nearly touching, so it fails. The second pair is the same size, but the centres are at least 24 pixels apart, so 24 pixel circles around them do not overlap and it passes by the spacing exception. The third pair is 44 pixels and comfortable on a phone.

Making targets bigger without changing the look

You do not need giant icons. Make the clickable area bigger with padding, while the icon stays small:

CSS
.icon-button {
  min-width: 44px;
  min-height: 44px;
  display: inline-grid;
  place-items: center;
  padding: 10px;
}

/* Bigger targets only for touch screens */
@media (pointer: coarse) {
  .toolbar button { min-height: 48px; }
}

The same idea applies to links in menus: put the padding on the <a> itself, not on the <li> around it, so the whole visible row is clickable. And remember that a <label> makes its text part of a checkbox's clickable area, which is a free way to enlarge small form controls.

Gestures, dragging and motion

Three more criteria protect people who cannot make precise or complex movements:

  • 2.5.1 Pointer Gestures (A): anything that needs a path-based gesture (a swipe or a drawn shape) or several fingers (pinch to zoom) must also work with a single tap or click. A swipeable carousel needs Previous and Next buttons; a map needs + and - zoom buttons.
  • 2.5.7 Dragging Movements (AA, new in 2.2): anything done by dragging must also be possible with single clicks, unless dragging is essential. A drag-and-drop list needs "Move up" and "Move down" buttons, for example.
  • 2.5.4 Motion Actuation (A): features triggered by shaking or tilting the device need a normal control as well, and the motion response can be turned off.

Here is a priority list that can be reordered with simple buttons instead of dragging:

HTMLTry it yourself
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Reorder Without Dragging</title>
  <style>
    li { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
    li span { flex: 1; }
    button { min-width: 44px; min-height: 44px; }
  </style>
</head>
<body>
  <h1>Priya's study plan, in order</h1>
  <ol id="plan">
    <li><span>Physics: optics</span><button type="button" data-move="up">Move up</button><button type="button" data-move="down">Move down</button></li>
    <li><span>Maths: integration</span><button type="button" data-move="up">Move up</button><button type="button" data-move="down">Move down</button></li>
    <li><span>Chemistry: organic</span><button type="button" data-move="up">Move up</button><button type="button" data-move="down">Move down</button></li>
  </ol>
  <p id="status" role="status"></p>

  <script>
    const plan = document.querySelector("#plan");
    plan.addEventListener("click", (event) => {
      const button = event.target.closest("button");
      if (!button) return;
      const item = button.closest("li");
      const subject = item.querySelector("span").textContent;
      if (button.dataset.move === "up" && item.previousElementSibling) {
        item.previousElementSibling.before(item);
      } else if (button.dataset.move === "down" && item.nextElementSibling) {
        item.nextElementSibling.after(item);
      }
      button.focus();
      const position = [...plan.children].indexOf(item) + 1;
      document.querySelector("#status").textContent = subject + " is now number " + position + ".";
    });
  </script>
</body>
</html>

After each move, focus stays on the pressed button (which moved with its item) and a status message announces the new position. A drag-and-drop version could be added on top for mouse users, but these buttons make sure nobody depends on it. To give each button a more specific name, such as "Move Physics up", you could add visually hidden text, as you learned in Links vs Buttons.

Let users cancel a tap

2.5.2 Pointer Cancellation (A) says an action should happen when the pointer is released, not when it is pressed down. Then a user who touches the wrong button can slide their finger away before lifting it, and nothing happens. The normal click event already works this way.

JavaScript
// Fires on press: no chance to cancel a mistake
deleteButton.addEventListener("pointerdown", deleteOrder);

// Fires on release over the same element: can be cancelled
deleteButton.addEventListener("click", deleteOrder);

Common mistakes

  • Icon buttons 16 pixels wide with no spacing. Use padding to reach at least 24 pixels, ideally 44.
  • Close buttons in a corner of a pop-up, touching the edge. Give them size and space.
  • Swipe-only carousels and drag-only sliders. Add buttons or a number input.
  • Actions on mousedown, touchstart or pointerdown. Use click unless you have a strong reason.
  • Removing default focus and size from checkboxes with custom CSS. Custom controls lose the user agent exception and must meet the size themselves.

Key points

  • WCAG 2.5.8 (AA) asks for targets of at least 24 by 24 CSS pixels, or enough spacing around smaller ones.
  • 2.5.5 (AAA) and mobile platform guidelines recommend 44 to 48 pixels.
  • Enlarge hit areas with padding and min-width/min-height instead of bigger icons.
  • Gestures and dragging need single-pointer alternatives (2.5.1 and 2.5.7).
  • Trigger actions on release (click) so users can cancel mistakes (2.5.2).

Exercise

A photo gallery on a Kochi homestay site lets guests change photos only by swiping, and its close button is a 14 by 14 pixel "x" in the top corner. Write HTML and CSS for a better version: Previous and Next buttons and a close button that each have at least a 44 by 44 pixel target.

Show solution
HTML
<div class="gallery" aria-label="Homestay photos">
  <button type="button" class="close">Close gallery</button>
  <img src="room-1.jpg" alt="Double room with a window facing the backwaters">
  <button type="button" class="prev">Previous photo</button>
  <button type="button" class="next">Next photo</button>
</div>
<style>
  .gallery button {
    min-width: 44px;
    min-height: 44px;
    padding: 8px 14px;
  }
</style>

Swiping can stay as an extra, but the Previous and Next buttons give a single-tap alternative, and every button now has at least a 44 by 44 pixel target with a clear text name.

Quick Quiz

1. What is the minimum target size in WCAG 2.2 at level AA?

2. A link in the middle of a paragraph is smaller than 24 pixels tall. Does it fail 2.5.8?

3. A to-do app lets users reorder items only by dragging. Which criterion does it fail?

4. Which event lets users cancel an accidental tap by sliding their finger away?

Learn Web Accessibility with a mentor

Free lessons get you started. Our Full Stack Web Development training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call