2.5.7 Level AA Guideline 2.5 Input Modalities Added in WCAG 2.2 Not detectable automatically

Dragging Movements

Functionality that uses a dragging movement can be achieved with a single pointer without dragging, unless dragging is essential.

Who this affects

Users with tremor, limited dexterity, or a head pointer, who can tap accurately but cannot hold and drag along a path. Drag-only reordering, sliders, and map panning exclude them.

The failure and the fix

Each example below is a self-contained page, loaded in a frame so its markup cannot affect this page. Open either one on its own to test it with a keyboard or screen reader.

Fails 2.5.7

Open the failing example in a new tab

fail.html — the problem

<h1>Your reading list</h1>

<!-- FAILURE 1: reordering is drag-only. There are no move up / move down
     buttons and no keyboard route.

     Who this excludes: anyone with tremor who cannot hold a pointer down and
     move it accurately; anyone using a head pointer or eye tracker, which
     cannot express "press and hold along a path"; and every keyboard user.
     Note this is a superset of 2.1.1 - it also fails for people who CAN use a
     pointer but cannot drag. -->
<p>Drag the titles to reorder your list.</p>
<ul class="list" id="list">
  <li draggable="true">Tidal Flats</li>
  <li draggable="true">The Long Field</li>
  <li draggable="true">Salt</li>
</ul>

<!-- FAILURE 2: a custom slider that can only be dragged. No arrow keys, no
     text input, no stepper buttons. -->
<h2>Maximum price</h2>
<div class="slider-track" id="track">
  <div class="slider-knob" id="knob" role="img" aria-label="Price slider, drag to set"></div>
</div>
<p id="price">£0</p>

Meets 2.5.7

Open the passing example in a new tab

pass.html — the fix

<h1>Your reading list</h1>

<!-- FIX 1: Move up and Move down buttons. Each is a single tap or a single
     Enter press - no path, no press-and-hold. Drag can still be offered on top
     of this for people who prefer it; the criterion only requires that it not
     be the ONLY way.

     The status region announces the result, so a screen reader user knows the
     move happened and where the item landed. -->
<ul class="list" id="list">
  <li>Tidal Flats
    <span class="controls">
      <button type="button" class="button button--secondary" onclick="move(this,-1)">
        <span aria-hidden="true">↑</span><span class="visually-hidden">Move Tidal Flats up</span></button>
      <button type="button" class="button button--secondary" onclick="move(this,1)">
        <span aria-hidden="true">↓</span><span class="visually-hidden">Move Tidal Flats down</span></button>
    </span>
  </li>
  <li>The Long Field
    <span class="controls">
      <button type="button" class="button button--secondary" onclick="move(this,-1)">
        <span aria-hidden="true">↑</span><span class="visually-hidden">Move The Long Field up</span></button>
      <button type="button" class="button button--secondary" onclick="move(this,1)">
        <span aria-hidden="true">↓</span><span class="visually-hidden">Move The Long Field down</span></button>
    </span>
  </li>
  <li>Salt
    <span class="controls">
      <button type="button" class="button button--secondary" onclick="move(this,-1)">
        <span aria-hidden="true">↑</span><span class="visually-hidden">Move Salt up</span></button>
      <button type="button" class="button button--secondary" onclick="move(this,1)">
        <span aria-hidden="true">↓</span><span class="visually-hidden">Move Salt down</span></button>
    </span>
  </li>
</ul>
<p id="order" role="status"></p>

<!-- FIX 2: the native range input. It can be dragged, but it also responds to
     arrow keys, Home and End, and works with voice control - all for free.
     Building a slider from divs throws all of that away. -->
<h2><label for="price">Maximum price</label></h2>
<input type="range" id="price" min="0" max="50" step="5" value="25"
       oninput="document.getElementById('out').textContent = '£' + this.value">
<p>Showing books up to <span id="out">£25</span></p>

<!-- The exception is narrow: dragging may be the only mechanism where it is
     ESSENTIAL - a drawing canvas, or a signature pad, where the path itself is
     the data. Reordering, sliders, kanban boards and map panning are never
     essential drags. -->

How to test it

Find every drag interaction — reorderable lists, sliders, kanban boards, drag-to-upload, map panning. Confirm a click or tap alternative exists: up and down buttons, a numeric input, arrow-key panning.

  • Automated

    Requires finding drag handlers and testing for a non-drag path to the same result.

    No axe rule maps to this criterion. It has to be checked by a person.

  • Keyboard

    Unplug the mouse. Move through the page with Tab, Shift+Tab, Enter, Space and the arrow keys. See the keyboard testing script.

  • Screen reader

    Listen to both examples with NVDA, JAWS, VoiceOver or TalkBack and compare what is announced. See the screen reader cheat sheets.

  • Visual

    Zoom to 200% and 400%, narrow the viewport to 320 px, and apply the text-spacing overrides. See the visual testing procedures.

In the specification