Provide Single-Pointer Alternatives for Complex Gestures
All functionality that uses multipoint (like pinch-to-zoom) or path-based gestures (like swiping or dragging) for operation must be operable using a single pointer (like a simple tap or click) without requiring the complex gesture, unless the gesture is essential (e.g., drawing) or determined by the user agent (like browser pinch-zoom).
Why It Matters
Users with certain motor disabilities may be unable to perform complex gestures like pinching, swiping, or precise dragging. Relying solely on these gestures for core functionality (like zooming a map, advancing a carousel, or deleting an item) can lock these users out. Providing single-pointer alternatives ensures broader accessibility.
Fixing the Issue
For any function triggered by a complex gesture, provide an alternative control that uses only a simple click or tap. For example:
- If using pinch-to-zoom on a map, also provide ‘+’ and ‘-‘ buttons for zooming.
- If using swipe to navigate a carousel, also provide ‘Previous’ and ‘Next’ buttons.
- If using drag-and-drop to reorder items, also provide buttons or menu options to move items up/down.
- Ensure these alternative controls are clearly visible and keyboard accessible.
Good Code Example
A carousel with both swipe gestures and button controls:
-
<div class="carousel-container"> <button class="prev-btn" aria-label="Previous Slide">‹</button> <div class="carousel-slides" id="slides"> <div class="slide">Slide 1</div> <div class="slide">Slide 2</div> <div class="slide">Slide 3</div> </div> <button class="next-btn" aria-label="Next Slide">›</button> </div> <script> // Basic carousel logic (conceptual) const slidesContainer = document.getElementById('slides'); const prevBtn = document.querySelector('.prev-btn'); const nextBtn = document.querySelector('.next-btn'); let currentSlide = 0; const totalSlides = slidesContainer.children.length; function showSlide(index) { // Logic to display the slide at the given index console.log("Showing slide:", index + 1); // Example: slidesContainer.style.transform = `translateX(-${index * 100}%)`; } prevBtn.addEventListener('click', () => { currentSlide = (currentSlide > 0) ? currentSlide - 1 : totalSlides - 1; showSlide(currentSlide); }); nextBtn.addEventListener('click', () => { currentSlide = (currentSlide < totalSlides - 1) ? currentSlide + 1 : 0; showSlide(currentSlide); }); // Add touch/swipe event listeners (conceptual) // slidesContainer.addEventListener('touchstart', handleTouchStart, false); // slidesContainer.addEventListener('touchmove', handleTouchMove, false); // function handleTouchStart(evt) { /* Record start position */ } // function handleTouchMove(evt) { /* Detect swipe, call showSlide */ } showSlide(currentSlide); // Show initial slide </script> <style> /* Basic styling */ .carousel-container { position: relative; overflow: hidden; width: 300px; } .carousel-slides { display: flex; /* Add transition */ } .slide { min-width: 100%; box-sizing: border-box; border: 1px solid #ccc; padding: 20px; text-align: center; } .prev-btn, .next-btn { position: absolute; top: 50%; transform: translateY(-50%); background: rgba(0,0,0,0.5); color: white; border: none; padding: 5px 10px; cursor: pointer; z-index: 10; } .prev-btn { left: 5px; } .next-btn { right: 5px; } </style>
Bad Code Example
Functionality relies solely on a path-based gesture (swipe):
-
<div class="swipe-gallery"> </div> <script> // Assume JavaScript here implements swipe detection // to navigate gallery items, but provides NO buttons // or other single-pointer controls. // Users unable to swipe cannot navigate the gallery. </script>
Search Ultimate Guide

Free eBook
Integrating Accessibility Compliance Into Your Budget
A Practical Guide for Healthcare Leaders Navigating the New HHS Ruling
Need Help with Compliance?
Our team is here to guide you through the process of meeting accessibility standards. Contact us today to get started.