WCAG 2.5.7: Dragging Movements
All functionality that uses a dragging movement can also be operated by a single pointer without dragging, unless dragging is essential or is determined by the user agent. Meeting this Level AA criterion means people who cannot press, hold, and precisely move a pointer — because of tremor, limited dexterity, or the input device they use — can still complete the same task with a simple tap or click.
The success criterion, in full
All functionality that uses a dragging movement for operation can be achieved by a single pointer without dragging, unless dragging is essential or the functionality is determined by the user agent and not modified by the author.
Why dragging alternatives matter
A dragging movement is one of the most demanding actions an interface can ask for. The user has to acquire a small target, press and hold the pointer down, move it accurately along a path, and release at exactly the right place — all in one uninterrupted gesture. That coordination is difficult or impossible for a large number of people: those with hand tremor, arthritis, Parkinson's disease, or muscular conditions; people using a head pointer, mouth stick, eye-gaze, or single-switch input; and anyone whose device makes sustained precise motion awkward, such as a trackpad user with a repetitive strain injury or someone on a touchscreen in a moving vehicle.
When dragging is the only way to reorder a list, set a value, or move a card, those users are locked out of the feature entirely. WCAG 2.5.7 fixes this without banning drag: it simply requires that a single-pointer alternative — a tap or click that needs no holding and no travel — reaches the same outcome. That alternative benefits everyone, including people on small screens where an accidental drag is easy to trigger.
What counts as a dragging movement
A dragging movement, in WCAG terms, is an operation where you set the pointer down on a starting point, keep it pressed while moving, and lift it at a different end point — and the difference between those two points is what triggers the action. Three details decide whether 2.5.7 applies:
- 1
The path is what matters, not just the endpoints. If the interaction depends on the pointer travelling from A to B while pressed — a slider thumb, a sortable row, a card moving between columns — it is a dragging movement and needs an alternative.
- 2
A single-pointer alternative means one tap or click. The alternative must not itself require dragging or a path-based gesture. Tapping a “move up” button, clicking a destination, or choosing from a menu all qualify; a two-finger swipe or a different drag does not.
- 3
Path-based gestures are a different criterion. Multi-point or directional gestures such as pinch-to-zoom or a two-finger swipe are covered by 2.5.1 Pointer Gestures. 2.5.7 is specifically about drag-and-hold operations that move something from one place to another.
Rule of thumb:for every place a user can drag something, ask “can I reach the exact same result with a single tap or click?” If the answer is no, you owe that feature a non-drag alternative.
The two exceptions
A dragging movement may lack a single-pointer alternative and still conform only if one of these two exceptions genuinely applies. Both are narrow — most drag features in real products do not qualify.
1. Essential
The dragging movement is essential to the function, or is determined by the user agent.
If the drag is genuinely essential — meaning the outcome cannot be achieved any other way without fundamentally changing the activity — it is exempt. A freehand digital drawing or signature is the classic example: the path the pointer travels is the information itself, so there is no meaningful single-tap equivalent. Movements that the user agent (browser or platform) provides, such as the native scrollbar thumb, are also covered. Be honest with this exception: reordering a list, adjusting a slider, or moving a card between columns is almost never essential, because a tap-based alternative produces the same result.
2. User-agent control
The drag is handled entirely by the browser and not built by the author.
When the dragging behavior comes from a default control the browser renders and you have not re-implemented it, the responsibility sits with the user agent, not you. A native range input's thumb or a browser scrollbar are examples. The moment you build a custom slider, custom scrollbar, or custom drag handle with JavaScript and pointer events, this exception no longer applies and you must supply a single-pointer alternative yourself.
Accessible patterns for common drag features
Sortable / reorderable lists
Add explicit “Move up” and “Move down” buttons (or a “Move to…” menu) on each row. The drag handle can stay for pointer users who prefer it; the buttons give everyone else a single-tap path. Announce each move with a live region so screen reader users hear the new position.
Kanban boards
Provide a “Move to column” control on each card — a menu or set of buttons naming each column. A user selects the destination with one tap instead of dragging the card across the board.
Custom sliders and range controls
Let users click anywhere on the track to jump the thumb to that point, and add stepper buttons (− / +) for fine adjustment. Better still, build on a native <input type="range"> which already supports clicking and arrow keys.
Maps and pannable canvases
Offer directional pan buttons (up, down, left, right) and zoom in/out buttons so the view can be moved without dragging. Most mapping libraries include these controls — make sure they are enabled and reachable.
Color pickers and 2-D selectors
Alongside the draggable swatch area, provide numeric inputs (hue, saturation, RGB, or HEX) so a value can be entered or clicked without dragging the selector.
Code examples
Reorderable list with move buttons (React)
Keep your drag-and-drop if you have it, but add single-pointer move controls that produce the identical result and announce the change to assistive technology.
function ReorderableList({ items, setItems }) {
const [status, setStatus] = useState("")
function move(index, direction) {
const target = index + direction
if (target < 0 || target >= items.length) return
const next = [...items]
;[next[index], next[target]] = [next[target], next[index]]
setItems(next)
setStatus(`${next[target].label} moved to position ${target + 1}`)
}
return (
<ul>
{items.map((item, i) => (
<li key={item.id} className="flex items-center gap-2">
<span className="flex-1">{item.label}</span>
{/* Single-pointer alternatives to dragging */}
<button
type="button"
onClick={() => move(i, -1)}
disabled={i === 0}
aria-label={`Move ${item.label} up`}
className="min-w-[44px] min-h-[44px]"
>
↑
</button>
<button
type="button"
onClick={() => move(i, 1)}
disabled={i === items.length - 1}
aria-label={`Move ${item.label} down`}
className="min-w-[44px] min-h-[44px]"
>
↓
</button>
</li>
))}
{/* Live region announces the new position */}
<li aria-live="polite" className="sr-only">
{status}
</li>
</ul>
)
}Custom slider: click the track as a drag alternative
If you must build a custom slider, let a single click on the track set the value, and expose stepper buttons for precision. A native range input is still the better default.
function Slider({ value, min, max, onChange }) {
function handleTrackClick(e) {
const rect = e.currentTarget.getBoundingClientRect()
const ratio = (e.clientX - rect.left) / rect.width
onChange(Math.round(min + ratio * (max - min)))
}
return (
<div className="flex items-center gap-2">
<button type="button" aria-label="Decrease"
onClick={() => onChange(Math.max(min, value - 1))}>−</button>
{/* Clicking the track jumps the thumb — no drag needed */}
<div
role="slider"
tabIndex={0}
aria-valuenow={value}
aria-valuemin={min}
aria-valuemax={max}
onClick={handleTrackClick}
onKeyDown={(e) => {
if (e.key === "ArrowRight") onChange(Math.min(max, value + 1))
if (e.key === "ArrowLeft") onChange(Math.max(min, value - 1))
}}
className="relative h-2 flex-1 bg-slate-200"
>
<span
className="absolute h-4 w-4 -translate-x-1/2 rounded-full bg-blue-600"
style={{ left: `${((value - min) / (max - min)) * 100}%` }}
/>
</div>
<button type="button" aria-label="Increase"
onClick={() => onChange(Math.min(max, value + 1))}>+</button>
</div>
)
}Prefer the native range input
The simplest way to satisfy 2.5.7 for a slider is to not build one: a native range input passes under the User-agent control exception and supports clicking and keyboard out of the box.
<label for="volume">Volume</label>
<input
type="range"
id="volume"
min="0"
max="100"
value="50"
/>
<!-- Browser provides click-on-track and arrow-key operation,
so no custom single-pointer alternative is required. -->Common mistakes
- Shipping a drag-and-drop reorder, kanban, or slider with no non-drag path at all — the single most frequent 2.5.7 failure.
- Offering a keyboard alternative but no single-pointer one. Keyboard support satisfies 2.1.1, not 2.5.7; a mouse or touch user who cannot drag still needs a tap-based option.
- Making the 'alternative' another gesture — a swipe or a second drag. The alternative must be a single tap or click with no path.
- Over-claiming the Essential exception for features like sortable lists or sliders. Those have obvious tap-based equivalents, so the exception does not apply.
- Re-implementing a scrollbar or slider in JavaScript and assuming the User-agent control exception still covers it. Once you build it yourself, you own the alternative.
- Forgetting to announce the result of the single-pointer action. Moving an item should update a live region so screen reader users get the same feedback drag users see.
How to test for 2.5.7
- 1
Inventory every drag interaction
List all features operated by dragging: sliders, sortable and reorderable lists, kanban boards, hand-dragged carousels, resizable panels, map panning, drag-to-select, and drawing or signature fields.
- 2
Try each task with single taps or clicks only
For every drag feature, attempt the same outcome using only single presses — no holding and moving. If a control lets you complete it, it passes; if dragging is the only route, it likely fails.
- 3
Confirm the alternative is truly single-pointer
Check that the alternative is not itself a gesture or a second drag. A tap on a button, a click on a destination, or a menu selection all qualify.
- 4
Judge the exceptions honestly
Only accept a missing alternative when dragging is genuinely essential (freehand drawing, signatures) or entirely user-agent-provided (a native range or scrollbar you have not re-implemented).
- 5
Test with mouse and touch
Automated tools rarely detect dragging alternatives, so verify manually on a desktop pointer and on a real touchscreen. Confirm feedback is announced to screen readers.
Run a full sweep with our Mobile Accessibility Checker and audit a live URL with the URL Accessibility Auditor.
Related success criteria
2.5.8 Target Size (Minimum) — AA (new in 2.2)
The sibling pointer-input criterion. The single-pointer buttons you add for 2.5.7 must also meet the 24×24 CSS pixel target size, so the two are usually evaluated together.
2.5.1 Pointer Gestures — A
Covers multipoint and path-based gestures such as pinch and swipe. Closely related to 2.5.7 but distinct: 2.5.1 is about complex gestures, 2.5.7 about press-and-move dragging.
2.1.1 Keyboard — A
The complementary path: a drag feature needs a keyboard route for 2.1.1 as well as a single-pointer route for 2.5.7. Robust interactions provide both.
Keyboard Accessibility Guide
Practical patterns for operating drag-and-drop, sliders, and reorderable lists from the keyboard — the counterpart to the pointer alternatives on this page.
Frequently asked questions
What does WCAG 2.5.7 Dragging Movements require?
WCAG 2.5.7 requires that any functionality operated by a dragging movement can also be operated by a single pointer without dragging — unless the dragging is essential or is handled by the user agent. A dragging movement means pressing down on a target, moving the pointer while it stays down, and releasing at a different location. The single-pointer alternative is typically a tap, click, or press. It is a Level AA success criterion added in WCAG 2.2.
Is WCAG 2.5.7 the same as keyboard accessibility (2.1.1)?
No, they are separate criteria and satisfying one does not satisfy the other. WCAG 2.1.1 Keyboard requires that functionality is operable with a keyboard. WCAG 2.5.7 Dragging Movements is specifically about pointer input — it requires a single-pointer (tap or click) alternative to dragging, which helps people who use a mouse, touchscreen, head pointer, or eye-gaze but struggle with the sustained, precise motion a drag demands. A drag-and-drop feature needs both a keyboard path (for 2.1.1) and a single-pointer path (for 2.5.7).
Does a slider built with an input type=range pass WCAG 2.5.7?
A native range input passes under the User-agent control exception because the browser provides the thumb and its dragging behavior, and it can also be operated with clicks on the track and arrow keys. If you replace it with a custom slider built from divs and pointer-event handlers, the exception no longer applies: you must add a single-pointer alternative such as clicking a point on the track to move the thumb, or plus and minus buttons that step the value.
How do I make a drag-and-drop list accessible for 2.5.7?
Keep the drag if you like, but add a single-pointer alternative that produces the same result. Common patterns are up and down (or move-to) buttons on each item, a 'move to' menu that lets the user pick a destination with a tap, or click-to-select then click-to-place. None of these require holding a pointer down and moving it. Remember to also provide a keyboard path and to announce the new position with a live region so screen reader users get feedback.
Does 2.5.7 mean I have to remove drag-and-drop?
No. The criterion does not ban dragging — it requires that dragging is not the only way. You can keep a rich drag interface for the people who prefer it and simply add a non-drag path (buttons, menus, or tap-to-place) alongside it. Both can coexist in the same component.
How do I test for WCAG 2.5.7 compliance?
Inventory every feature that uses dragging: sliders, sortable and reorderable lists, kanban boards, carousels dragged by hand, resizable panels, map panning, drag-to-select, and signature or drawing fields. For each one, try to complete the same task using only single taps or clicks — no press-and-move. If you cannot, it fails unless the drag is genuinely essential. Automated tools rarely detect this reliably, so manual testing with a mouse and on a touchscreen is required.