Kryteria sukcesu WCAG · Level AA

WCAG 2.5.7: Ruchy przeciągania

WCAG 2.5.7 wymaga, aby każdą funkcjonalność wykorzystującą ruch przeciągania można było również zrealizować za pomocą pojedynczego wskaźnika bez przeciągania, chyba że przeciąganie jest niezbędne. Zapewnia to, że użytkownicy z niepełnosprawnościami ruchowymi, którzy nie mogą w sposób niezawodny wykonywać gestów przeciągania, nadal mają dostęp do całej funkcjonalności.

Co oznacza ta zasada

WCAG 2.5.7 — Ruchy przeciągania (poziom AA, wprowadzony w WCAG 2.2) stanowi, że wszystkie funkcje, które do obsługi wykorzystują ruch przeciągania, muszą być dostępne za pomocą pojedynczej akcji wskaźnikiem bez przeciągania, z wyjątkiem sytuacji, gdy ruch przeciągania jest niezbędny dla danej funkcjonalności i nie istnieje żaden alternatywny mechanizm.

Ruch przeciągania jest zdefiniowany jako interakcja, w której wskaźnik jest wciśnięty, przytrzymany i przesunięty w nowe położenie, zanim zostanie zwolniony. Typowe przykłady to: sortowanie elementów listy metodą „przeciągnij i upuść”, zmiana rozmiaru paneli przez przeciąganie uchwytu dzielnika, używanie suwaka poprzez złapanie i przeciągnięcie kciuka, rysowanie na płótnie oraz zmiana kolejności kart kanban. Wszystkie te wzorce muszą mieć równoważną alternatywę opartą na pojedynczym wskaźniku — mechanizm, który użytkownik może aktywować bez konieczności trzymania przycisku wskaźnika podczas ruchu.

Ograniczenie do pojedynczego wskaźnika jest istotne. Alternatywa nie musi być skrótem klawiaturowym; może to być kliknięcie myszą, stuknięcie lub inna akcja, która obejmuje tylko jeden punkt kontaktu i nie wymaga utrzymywania ruchu podczas wciśnięcia. Na przykład suwak, który pozwala użytkownikom kliknąć bezpośrednio na torze, aby przeskoczyć do danej wartości, spełnia kryterium, ponieważ kliknięcie toru jest akcją pojedynczym wskaźnikiem bez przeciągania.

Co uznaje się za spełnienie: Lista z możliwością przeciągania, która dodatkowo oferuje przyciski strzałek góra/dół lub okno dialogowe „przenieś na pozycję”; suwak zakresu, który akceptuje kliknięcia w dowolnym miejscu toru; panel o zmiennym rozmiarze, który ma również pole wejściowe numeryczne lub możliwość zwinęcia po dwukrotnym kliknięciu; mapa, którą można przesuwać zarówno za pomocą klikanych strzałek nawigacyjnych, jak i przeciągania.

Co uznaje się za niespełnienie: Sortowalna lista, w której jedynym sposobem zmiany kolejności elementów jest ich przeciąganie; dzielnik panelu bez alternatywnego sposobu zmiany rozmiaru; przesyłanie plików, które akceptuje wyłącznie przeciąganie i upuszczanie, bez przycisku jako rozwiązania zapasowego; selektor koloru, w którym jedynym sposobem wyboru odcienia jest przeciąganie po pasku gradientu, bez alternatywy w postaci wartości numerycznej lub tekstowej.

Oficjalny wyjątek: Kryterium wprost dopuszcza interfejsy wyłącznie z przeciąganiem, gdy przeciąganie jest niezbędne — tzn. jego usunięcie zasadniczo zmieniłoby lub unieważniło daną aktywność. Klasycznym przykładem jest aplikacja do rysowania gestami lub widżet do składania podpisu. Ten wyjątek jest jednak celowo wąski; większość codziennych wzorców UI (suwaki, sortowalne listy, kolumny o zmiennym rozmiarze) nie jest uznawana za scenariusze, w których przeciąganie jest niezbędne.

Dlaczego to ma znaczenie

Niepełnosprawności ruchowe dotyczą znaczącej części światowej populacji. Według Światowej Organizacji Zdrowia ponad 1,3 miliarda osób na świecie — około 16% globalnej populacji — żyje z jakąś formą niepełnosprawności, a zaburzenia motoryczne lub fizyczne należą do najczęstszych kategorii. Schorzenia takie jak drżenie samoistne, choroba Parkinsona, urazy przeciążeniowe, hemiplegia, urazy rdzenia kręgowego oraz różnice w budowie kończyn utrudniają lub uniemożliwiają jednoczesne trzymanie wciśniętego przycisku wskaźnika i precyzyjne poruszanie wskaźnikiem.

Dla użytkownika z drżeniem rąk przeciągnięcie kciuka suwaka z jednego końca toru na drugi nie jest tylko niewygodne — może być całkowicie zawodne. Wskaźnik może się ześlizgnąć, przeciąganie może zostać przerwane w trakcie, albo wymagana precyzja po prostu przekracza możliwości rąk dotkniętych drżeniem. Tacy użytkownicy często polegają na alternatywach opartych na klikaniu, nawigacji klawiaturą lub urządzeniach przełącznikowych. Jeśli jedyną drogą do skorzystania z funkcji jest gest przeciągnięcia, cała funkcja jest dla nich de facto niedostępna.

Konkretny scenariusz: Rozważ stronę produktu w e‑commerce z filtrem zakresu cen zrealizowanym jako suwak zakresu z dwoma uchwytami. Użytkownik z ograniczoną precyzją ruchów próbuje zawęzić zakres cen, ale nie jest w stanie wiarygodnie przeciągnąć żadnego uchwytu do docelowej pozycji — wskaźnik dryfuje, uchwyt przeskakuje do błędnych wartości, a frustracja powoduje porzucenie zadania. Gdyby ten sam filtr udostępniał parę pól tekstowych z wartościami liczbowymi obok suwaka, użytkownik mógłby po prostu wpisać żądaną minimalną i maksymalną cenę i zatwierdzić. Ten pojedynczy dodatek przekształca funkcję niedostępną w w pełni dostępną przy minimalnym koszcie deweloperskim.

Poza niepełnosprawnościami ruchowymi, z alternatyw opartych na pojedynczym wskaźniku korzystają także użytkownicy ekranów dotykowych w trudnych warunkach — trzymający poręcz w transporcie publicznym, noszący rękawiczki lub używający rysika. Istotna jest też dostępność poznawcza: prostsze interakcje oparte na klikaniu zmniejszają obciążenie poznawcze w porównaniu z operacjami przeciągnij‑i‑upuść, które wymagają zrozumienia metafory przestrzennej przy jednoczesnym zachowaniu precyzji ruchowej.

Z punktu widzenia użyteczności i SEO zapewnienie, że elementy interaktywne są osiągalne za pomocą prostych akcji wskaźnikiem, zwykle prowadzi do czystszej architektury komponentów z lepszym znacznikiem semantycznym, co z kolei poprawia wykrywalność przez technologie asystujące i roboty wyszukiwarek.

Powiązane reguły Axe-core

WCAG 2.5.7 jest kryterium wymagającym testów manualnych. W momencie pisania axe-core nie zawiera zautomatyzowanej reguły, która mogłaby jednoznacznie wskazywać naruszenia tego kryterium. Powód wynika z samej natury kryterium: narzędzia automatyczne mogą wykryć, że na elemencie istnieje nasłuchiwacz zdarzenia przeciągania, ale nie są w stanie z całą pewnością stwierdzić, czy dostępna jest alternatywa bez przeciągania, czy ta alternatywa obejmuje tę samą funkcjonalność ani czy przeciąganie jest niezbędne. Taka ocena wymaga ludzkiej analizy projektu interakcji.

  • Audyt manualny — mechanizmy przeciągania i upuszczania: Testerzy muszą zidentyfikować każdy komponent na stronie, który reaguje na sekwencje mousedown/mousemove/mouseup lub ich odpowiedniki dotykowe (touchstart/touchmove/touchend) i sprawdzić, czy każdy z nich udostępnia alternatywny mechanizm obsługiwany za pomocą pojedynczego naciśnięcia wskaźnika bez przeciągania. Testerzy powinni również sprawdzić atrybut HTML5 draggable oraz powiązane nasłuchiwacze zdarzeń dragstart/drop jako sygnały funkcjonalności zależnej od przeciągania.
  • Audyt manualny — inspekcja zdarzeń wskaźnika: Korzystając z inspekcji nasłuchiwaczy zdarzeń w narzędziach deweloperskich przeglądarki lub narzędzi do audytu dostępności, takich jak Accessibility Insights for Web (które zawiera ręczną listę kontrolną dla 2.5.7), testerzy powinni sprawdzić komponenty pod kątem obsługi zdarzeń wskaźnika i potwierdzić, że pełny zakres wartości komponentu lub możliwość zmiany położenia jest osiągalna bez utrzymywanego ruchu wskaźnika.
  • Dlaczego automatyzacja nie może tego wykryć: Automatyczny skaner może wskazać, że element <div> ma nasłuchiwacz dragstart, ale nie może wiedzieć, czy kliknięcie pobliskiego przycisku z etykietą „Move up” zapewnia zgodną alternatywę. Wymaga to zrozumienia relacji między elementami UI a ich równoważnością funkcjonalną — zadania, które obecnie wykracza poza możliwości narzędzi analizujących DOM statycznie lub w czasie wykonywania.

Jak testować

  1. Podstawowy skan automatyczny: Uruchom axe DevTools lub Lighthouse na stronie, aby wykryć powiązane problemy ze wskaźnikiem lub sposobami wprowadzania danych. Choć żadna reguła axe nie mapuje się bezpośrednio na 2.5.7, przejrzenie problemów oznaczonych w ramach reguł 2.5.x dostarcza użytecznego kontekstu. Zanotuj komponenty, które axe oznacza jako mające niewystarczające wsparcie klawiatury, ponieważ często pokrywa się to ze wzorcami opartymi wyłącznie na przeciąganiu.
  2. Zidentyfikuj wszystkie komponenty z przeciąganiem: Otwórz Chrome DevTools, przejdź do panelu Elements i użyj zakładki Event Listeners, aby wyszukać obsługę dragstart, drag, drop, pointermove, mousemove i touchmove. Alternatywnie przeszukaj kod strony pod kątem atrybutu draggable oraz wzorców JavaScript takich jak .addEventListener('dragstart'. Wypisz każdy komponent, który wymaga przeciągania.
  3. Przetestuj każdy komponent z przeciąganiem pod kątem alternatyw: Dla każdego zidentyfikowanego komponentu spróbuj osiągnąć ten sam rezultat, używając wyłącznie pojedynczych kliknięć lub stuknięć — bez przeciągania. Dla suwaka kliknij bezpośrednio na torze w żądanej pozycji. Dla sortowalnej listy poszukaj przycisków przenoszenia lub opcji w menu kontekstowym. Dla panelu o zmiennym rozmiarze poszukaj sterowania opartego na dwukrotnym kliknięciu lub kliknięciu. Jeśli nie istnieje żadna alternatywa, kryterium jest niespełnione.
  4. Sprawdzenie nawigacji klawiaturą (sygnał wtórny): Przetestuj wszystkie komponenty z przeciąganiem, używając wyłącznie klawiatury (Tab, aby ustawić fokus, strzałki, Enter/Spacja). Choć wsparcie klawiatury jest objęte WCAG 2.1.1, obecność solidnego wsparcia klawiatury często koreluje z istnieniem alternatyw bez przeciągania, co czyni ten krok użytecznym potwierdzeniem. Użyj NVDA + Firefox, VoiceOver + Safari (macOS/iOS) lub JAWS + Chrome i sprawdź, czy pełna funkcjonalność komponentu jest dostępna bez urządzenia wskazującego.
  5. Weryfikacja na urządzeniu dotykowym: Na urządzeniu mobilnym lub korzystając z emulacji urządzenia dotykowego w Chrome DevTools spróbuj wykonać te same zadania, używając gestów stuknięcia (bez przytrzymywania i przesuwania). Potwierdź, że pojedyncze stuknięcia lub interakcje typu „tap-on-target” są wystarczające dla całej funkcjonalności.
  6. Udokumentuj wyniki: Dla każdego testowanego komponentu zanotuj, czy istnieje zgodna alternatywa oparta na pojedynczym wskaźniku, czy obejmuje pełen zakres funkcjonalności oraz czy operacja przeciągania może być uznana za niezbędną. Użyj listy kontrolnej testu manualnego dla WCAG 2.5.7 w Accessibility Insights for Web jako uporządkowanego przewodnika.

Jak naprawić

Suwak zakresu bez wsparcia kliknięcia w tor — niepoprawny

<!-- Slider that only responds to drag on the thumb;
     clicking the track does nothing -->
<div class='slider-container'>
  <div class='slider-track'>
    <div class='slider-thumb'
         id='priceSlider'
         onmousedown='startDrag(event)'>
    </div>
  </div>
</div>

Suwak zakresu z kliknięciem w tor i wejściem numerycznym — poprawny

<!-- Native <input type='range'> provides drag, click-on-track,
     and keyboard support natively. A numeric input offers an
     additional single-pointer alternative. -->
<label for='priceRange'>Maximum price: <span id='priceValue'>500</span> TL</label>
<input type='range'
       id='priceRange'
       name='priceRange'
       min='0'
       max='1000'
       value='500'
       step='10'
       aria-valuemin='0'
       aria-valuemax='1000'
       aria-valuenow='500'
       oninput='document.getElementById("priceValue").textContent = this.value;
                document.getElementById("priceNumber").value = this.value;'>
<label for='priceNumber'>Or enter a value:</label>
<input type='number'
       id='priceNumber'
       name='priceNumber'
       min='0'
       max='1000'
       value='500'>

Sortowalna lista z przeciąganiem i upuszczaniem bez alternatywy — niepoprawna

<!-- Items can only be reordered by dragging.
     No move buttons or keyboard reordering exist. -->
<ul id='taskList'>
  <li draggable='true' ondragstart='handleDrag(event)' id='item1'>Task One</li>
  <li draggable='true' ondragstart='handleDrag(event)' id='item2'>Task Two</li>
  <li draggable='true' ondragstart='handleDrag(event)' id='item3'>Task Three</li>
</ul>

Sortowalna lista z przeciąganiem i przyciskami przenoszenia — poprawna

<!-- Drag-and-drop is preserved for users who can use it.
     Move Up / Move Down buttons provide a single-pointer
     (and keyboard-accessible) alternative for every item. -->
<ul id='taskList' aria-label='Sortable task list'>
  <li draggable='true'
      ondragstart='handleDrag(event)'
      id='item1'>
    <span>Task One</span>
    <button type='button'
            onclick='moveItem("item1", -1)'
            aria-label='Move Task One up'>
      &uarr; Move Up
    </button>
    <button type='button'
            onclick='moveItem("item1", 1)'
            aria-label='Move Task One down'>
      &darr; Move Down
    </button>
  </li>
  <li draggable='true'
      ondragstart='handleDrag(event)'
      id='item2'>
    <span>Task Two</span>
    <button type='button'
            onclick='moveItem("item2", -1)'
            aria-label='Move Task Two up'>
      &uarr; Move Up
    </button>
    <button type='button'
            onclick='moveItem("item2", 1)'
            aria-label='Move Task Two down'>
      &darr; Move Down
    </button>
  </li>
</ul>

Panel dzielony o zmiennym rozmiarze bez alternatywy — niepoprawny

<!-- The divider can only be repositioned by dragging.
     No percentage input or preset-size buttons exist. -->
<div class='split-pane'>
  <div class='pane pane-left' id='leftPane'>Content A</div>
  <div class='divider'
       onmousedown='startResize(event)'
       aria-hidden='true'></div>
  <div class='pane pane-right' id='rightPane'>Content B</div>
</div>

Panel dzielony o zmiennym rozmiarze z przyciskami predefiniowanych rozmiarów — poprawny

<!-- The divider still supports dragging, but preset-layout
     buttons allow single-pointer repositioning. The divider
     is also keyboard-focusable with arrow-key support. -->
<div class='split-pane-wrapper'>
  <div class='split-controls' role='group' aria-label='Panel size presets'>
    <button type='button' onclick='setSplit(25)'>25 / 75</button>
    <button type='button' onclick='setsplit(50)'>50 / 50</button>
    <button type='button' onclick='setSplit(75)'>75 / 25</button>
  </div>
  <div class='split-pane'>
    <div class='pane pane-left' id='leftPane'>Content A</div>
    <div class='divider'
         role='separator'
         tabindex='0'
         aria-label='Resize panels'
         aria-valuenow='50'
         aria-valuemin='10'
         aria-valuemax='90'
         onmousedown='startResize(event)'
         onkeydown='resizeWithKeys(event)'>
    </div>
    <div class='pane pane-right' id='rightPane'>Content B</div>
  </div>
</div>

Typowe błędy

  • Implementowanie suwaków jako niestandardowych komponentów opartych na <div> bez wsparcia kliknięcia w tor, polegając wyłącznie na przeciąganiu elementu kciuka i nie obsługując zdarzeń click na samym torze, aby przeskoczyć wartość do klikniętej pozycji.
  • Zakładanie, że przeciąganie i upuszczanie plików jest jedynym potrzebnym mechanizmem przesyłania, bez zapewnienia widocznego, klikalnego przycisku wyboru pliku (<input type='file'>) jako obowiązkowego rozwiązania zapasowego obok strefy upuszczania.
  • Zbyt szerokie stosowanie wyjątku niezbędności — na przykład traktowanie sortowalnej listy zadań lub tablicy kanban jako „niezbędnego przeciągania”, podczas gdy przyciski Move Up/Down w pełni zaspokoiłyby potrzeby użytkowników bez utraty funkcjonalności.
  • Zapewnianie alternatyw klawiaturowych, ale nie alternatyw opartych na pojedynczym wskaźniku, błędna interpretacja WCAG 2.5.7 jako spełnionego wyłącznie przez wsparcie klawiatury. Kryterium wprost wymaga ścieżki opartej na pojedynczym wskaźniku; rozwiązania wyłącznie klawiaturowe odnoszą się do 2.1.1, a nie 2.5.7.
  • Ukrywanie przycisków przenoszenia lub pól numerycznych za stanami hover lub menu drugiego poziomu, które same wymagają interakcji przeciągania lub złożonych sekwencji wskaźnika, aby je ujawnić, co w praktyce niweczy dostępność alternatywy.
  • Ignorowanie urządzeń dotykowych poprzez testowanie alternatyw dla przeciągania wyłącznie z użyciem myszy na komputerze stacjonarnym, a następnie wdrażanie dla użytkowników na ekranach dotykowych, gdzie zachowanie gestów przeciągania i ich alternatyw może znacząco różnić się od implementacji desktopowej.
  • Używanie w CSS właściwości pointer-events: none na torze suwaka, aby zapobiec przypadkowym kliknięciom podczas przeciągania, co niezamierzenie blokuje alternatywę kliknięcia w tor wymaganą przez 2.5.7.
  • Brak alternatywy dla interakcji przesuwania/przeciągania mapy na osadzonych mapach lub niestandardowych wizualizacjach opartych na canvas, gdzie kliknięcie przycisków strzałek kierunkowych lub wprowadzenie współrzędnych stanowiłoby wystarczającą alternatywę opartą na pojedynczym wskaźniku.
  • Implementowanie alternatywy opartej na pojedynczym wskaźniku jako kolejnego celu przeciągania i upuszczania — na przykład tworzenie strefy „upuść tutaj”, która nadal wymaga przeciągania, zamiast rzeczywiście odmiennego modelu interakcji, takiego jak przycisk lub pole tekstowe.
  • Zapominanie o testowaniu alternatyw w pełnym zakresie wartości komponentu z przeciąganiem. Suwak, który pozwala użytkownikom kliknąć tylko kilka predefiniowanych pozycji na torze, ale nie dowolną pozycję, nie oferuje pełnej alternatywy, jeśli wersja z przeciąganiem obsługuje wartości ciągłe.

Związek z tureckimi regulacjami dostępności

Turecka Okrężnica Prezydencka 2025/10, opublikowana w Dzienniku Urzędowym nr 32933 w dniu 21 czerwca 2025 r., ustanawia kompleksowe krajowe ramy dostępności dla usług cyfrowych. Okrężnica wymaga, aby podmioty objęte regulacją stosowały się do Wytycznych dotyczących dostępności treści internetowych (WCAG) i wprost odwołuje się do zgodności na poziomie AA jako standardu uzyskania Erişilebilirlik Logosu (Logotyp Dostępności), oficjalnego znaku certyfikacji wydawanego przez Ministerstwo Rodziny i Usług Społecznych (Aile ve Sosyal Hizmetler Bakanlığı).

WCAG 2.5.7, jako kryterium poziomu AA wprowadzone w WCAG 2.2, mieści się w zakresie wymogów koniecznych do uzyskania i utrzymania Logotypu Dostępności. Dla organizacji, które polegają na interakcjach typu przeciągnij‑i‑upuść — takich jak platformy e‑commerce z suwakami filtrów produktów lub sortowalnymi listami życzeń, aplikacje bankowe z pulpitami zarządzania portfelem czy narzędzia rezerwacyjne biur podróży z selektorami zakresu dat — niezgodność z 2.5.7 stanowiłaby bezpośrednią przeszkodę w certyfikacji.

Podmioty objęte Okrężnicą Prezydencką 2025/10 obejmują szeroki przekrój tureckiej gospodarki cyfrowej: instytucje publiczne i organy administracji na szczeblu centralnym i lokalnym; banki i dostawców usług finansowych regulowanych przez Urząd Regulacji i Nadzoru Bankowego (BDDK); platformy e‑commerce działające w Turcji; szpitale i prywatnych świadczeniodawców usług zdrowotnych; operatorów telekomunikacyjnych z 200,000 lub większą liczbą abonentów; biura podróży i prywatne firmy transportowe; oraz szkoły prywatne upoważnione przez Ministerstwo Edukacji Narodowej (Milli Eğitim Bakanlığı — MoNE).

Dla tych organizacji brak zapewnienia alternatyw opartych na pojedynczym wskaźniku dla interakcji przeciągania nie jest jedynie niedociągnięciem technicznym — jest luką w zgodności, która może uniemożliwić certyfikację, narazić organizację na kontrolę regulacyjną i wykluczyć znaczną grupę użytkowników z niepełnosprawnościami ruchowymi. Statystyki niepełnosprawności w Turcji odzwierciedlają trendy globalne: miliony mieszkańców żyją ze schorzeniami wpływającymi na precyzję ruchów, a usługi cyfrowe, które polegają wyłącznie na gestach przeciągania, stawiają przed tą populacją niepotrzebne bariery.

W praktyce organizacje ubiegające się o Erişilebilirlik Logosu powinny uwzględnić WCAG 2.5.7 w swoich listach kontrolnych audytu dostępności, upewnić się, że wszystkie komponenty interaktywne zbudowane z użyciem funkcji przeciągania są przeanalizowane pod kątem zgodnych alternatyw oraz udokumentować swoje decyzje dotyczące zgodności — w tym wszelkie powołania się na wyjątek niezbędności — jako część Oświadczenia o Dostępności (Erişilebilirlik Beyanı), którego publikację i aktualizowanie okrężnica nakłada na podmioty objęte regulacją.