Operable · Level AA · 2.5.7
Dragging Movements
Anything operated by dragging — reordering a list, a range slider, a carousel you swipe, a color picker you drag across — needs a single-pointer alternative that doesn't require holding down and moving at the same time: a tap, a click, a pair of buttons. This covers anyone who can't perform a precise press-hold-move-release sequence, whether that's a hand tremor, a trackball, an eye-gaze system, or a touchscreen with no keyboard to fall back on.
- Motor
How to recognize it
Try to operate every draggable interaction using only single taps or clicks, with no holding and moving. A sortable list where picking an item up and dragging it to a new position is the only way to reorder it fails if there's no alternative. A range slider that only responds to dragging its handle — no arrow keys, no click-to-set — fails. A carousel that only advances by swipe with no visible previous/next buttons fails. Two things are explicitly out of scope, worth knowing so you don't over-apply this: the browser's own native page scrolling isn't covered (that's the user agent's responsibility, not the page author's), and if dragging is genuinely essential to what the interaction is — a freehand drawing tool, for instance — that's exempt too.
How to fix it
Add a single-pointer way to accomplish the same thing. For a sortable list, this is the exact same fix 2.1.1 needs for keyboard access: 'move up' / 'move down' buttons next to each item work for a mouse click, a screen tap, and a keyboard press all at once — one fix satisfies both criteria. For a range slider, use a real <input type="range"> instead of a custom drag-only widget; the native element gets click-to-set and arrow-key support for free. For a carousel, add visible previous/next buttons alongside the swipe gesture rather than relying on swipe alone.
Example
Avoid
<li draggable="true" ondragstart="handleDrag(event)">Item</li><div class="slider-handle" onmousedown="startDrag(event)"></div>
<!-- no click-to-set, no keyboard support --><div class="carousel" ontouchstart="startSwipe(event)">...</div>
<!-- no visible prev/next buttons -->Prefer
<li draggable="true" ondragstart="handleDrag(event)">Item <button aria-label="Move item up">↑</button> <button aria-label="Move item down">↓</button></li><input type="range" min="0" max="100"><div class="carousel">
<button aria-label="Previous slide">‹</button>
...
<button aria-label="Next slide">›</button>
</div>