Pinch-to-zoom, two-finger swipe, or multi-touch gesture controls exclude users with one functional hand, tremor, or other conditions that prevent multi-pointer input. WCAG 2.2 SC 2.5.1 (Pointer Gestures) is a Level A requirement: all functionality that uses multipoint or path-based gestures must also be operable with a single pointer using no path constraint. An image gallery that requires pinch-to-zoom with no zoom buttons cannot be used with one finger.
Low because multi-pointer gesture requirements are limited to specific UI components rather than the whole interface, but wherever they occur they create a hard exclusion violating WCAG 2.2 SC 2.5.1 at Level A.
For every multi-pointer gesture, provide single-pointer button controls that perform the same action.
// Image viewer with single-pointer zoom buttons alongside pinch-to-zoom
export function ImageViewer({ src }: { src: string }) {
const [scale, setScale] = useState(1)
return (
<div>
<div className="flex gap-2 mb-2">
<button onClick={() => setScale(s => Math.max(1, s - 0.25))} aria-label="Zoom out">
−
</button>
<button onClick={() => setScale(s => Math.min(4, s + 0.25))} aria-label="Zoom in">
+
</button>
<button onClick={() => setScale(1)} aria-label="Reset zoom">
Reset
</button>
</div>
<img
src={src}
style={{ transform: `scale(${scale})`, transformOrigin: 'top left' }}
alt=""
/>
</div>
)
}
For swipeable carousels, add previous/next buttons. For map panning, add directional controls. The pointer gesture can remain — it just cannot be the only way.
ID: accessibility-wcag.understandable.pointer-alternative
Severity: low
What to look for: Enumerate every relevant item. Check for multi-pointer gestures like pinch-to-zoom, two-finger tap, or swipe with multiple fingers. Verify that single-pointer alternatives exist (e.g., buttons for zoom).
Pass criteria: At least 1 of the following conditions is met. All multi-pointer gestures have single-pointer alternatives. Path-dependent gestures (draw, swipe in specific pattern) have simpler alternatives.
Fail criteria: Functionality requires complex multi-pointer gestures with no alternative.
Skip (N/A) when: The project has no pointer-based gestures.
Detail on fail: Example: "Image gallery requires pinch-to-zoom with no zoom buttons. Slider requires swipe gesture with no keyboard or button controls"
Remediation: Provide alternative controls:
// Instead of pinch-to-zoom only, add buttons
<button onClick={() => setZoom(zoom + 1)}>Zoom In</button>
<button onClick={() => setZoom(zoom - 1)}>Zoom Out</button>
<Image style={{ transform: `scale(${zoom})` }} />