Respektowanie preferencji ruchu użytkowników
Opublikowany: 2022-03-10prefers-reduced-motion
ma doskonałe wsparcie we wszystkich nowoczesnych przeglądarkach od kilku lat. W tym artykule Michelle Barker wyjaśnia, dlaczego nie ma powodu, aby nie używać go dzisiaj, aby uczynić swoje witryny bardziej dostępnymi.Podczas pracy z ruchem w sieci należy wziąć pod uwagę, że nie wszyscy doświadczają go w ten sam sposób. To, co dla niektórych może wydawać się gładkie i gładkie, może być denerwujące lub rozpraszające dla innych – lub, co gorsza, wywoływać uczucie choroby, a nawet powodować drgawki. Witryny z dużą ilością ruchu mogą również mieć większy wpływ na żywotność baterii urządzeń mobilnych lub powodować zużycie większej ilości danych (na przykład automatyczne odtwarzanie filmów będzie wymagać więcej danych użytkownika niż statyczny obraz). To tylko niektóre z powodów, dla których witryny z dużą ilością ruchu mogą nie być pożądane dla wszystkich.
Większość nowych systemów operacyjnych umożliwia użytkownikowi ustawienie preferencji ruchu w ustawieniach na poziomie systemu. Zapytanie o media prefers-reduced-motion
(część specyfikacji zapytań o media na poziomie 5) pozwala nam wykryć preferencje ruchu na poziomie systemu i zastosować style CSS, które je uwzględniają.
Dwie opcje prefers-reduced-motion
to reduce
lub no-preference
. Możemy użyć go w naszym CSS w następujący sposób, aby wyłączyć animację elementu, jeśli użytkownik wyraźnie ustawił preferencję dla zmniejszonego ruchu :
.some-element { animation: bounce 1200ms; } @media (prefers-reduced-motion: reduce) { .some-element { animation: none; } }
I odwrotnie, możemy ustawić animację tylko wtedy, gdy użytkownik nie ma preferencji ruchu. Ma to tę zaletę, że zmniejsza ilość kodu, który musimy napisać, i oznacza, że mniej prawdopodobne jest, że zapomnimy uwzględnić preferencje ruchu użytkowników:
@media (prefers-reduced-motion: no-preference) { .some-element { animation: bounce 1200ms; } }
Dodatkową zaletą jest to, że starsze przeglądarki, które nie obsługują prefers-reduced-motion
, ignorują regułę i wyświetlają tylko nasz oryginalny, pozbawiony ruchu element.
Która zasada?
W przeciwieństwie do zapytań o media min-width
i max-width
, gdzie mniej więcej ustalony konsensus dotyczy przede wszystkim urządzeń mobilnych (dlatego faworyzuje min-width
), nie ma jednego „właściwego” sposobu napisania stylów z ograniczonym ruchem. Preferuję drugi przykład (stosowanie animacji tylko wtedy, gdy prefers-reduced-motion: no-preference
oznacza prawdę) z powodów wymienionych powyżej. Tatiana Mac napisała ten doskonały artykuł, który omawia niektóre podejścia, które programiści mogą rozważyć, a także wiele innych świetnych punktów, w tym kluczowe pytania, które należy zadać podczas projektowania z ruchem w sieci.
Jak zawsze, komunikacja w zespole i spójna strategia są kluczem do zapewnienia, że wszystkie podstawy są uwzględnione, jeśli chodzi o dostępność sieci.
Praktyczne zastosowanie: stosowanie prefers-reduced-motion
celu zachowania podczas przewijania
prefers-reduced-motion
ma wiele zastosowań poza stosowaniem (lub niestosowaniem) animacji klatek kluczowych lub przejść. Jednym z przykładów jest płynne przewijanie. Jeśli ustawimy scroll-behaviour: smooth
na naszym elemencie html
, gdy użytkownik kliknie w link kotwiczny na stronie, zostanie on płynnie przewinięty do odpowiedniej pozycji na stronie ( obecnie nieobsługiwane w Safari ):
html { scroll-behavior: smooth; }
Niestety w CSS nie mamy obecnie dużej kontroli nad tym zachowaniem. Jeśli mamy długą stronę z treścią, strona przewija się bardzo szybko, co może być dość nieprzyjemnym doświadczeniem dla osoby z wrażliwością na ruch. Zawijając je w zapytanie o media, możemy zapobiec zastosowaniu tego zachowania w przypadkach, gdy użytkownik ma preferencję reduced-motion
:
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
Catering dla preferencji ruchu w JavaScript
Czasami musimy zastosować ruch w JavaScript, a nie CSS. W podobny sposób możemy wykryć preferencje ruchu użytkownika za pomocą JS, używając matchMedia
. Zobaczmy, jak możemy warunkowo zaimplementować zachowanie płynnego przewijania w naszym kodzie JS:
/* Set the media query */ const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') button.addEventListener('click', () => { /* If the media query matches, set scroll behavior variable to 'auto', otherwise set it to 'smooth' */ const behavior = prefersReducedMotion.matches ? 'auto' : 'smooth' /* When the button is clicked, the user will be scrolled to the top */ window.scrollTo({ x: 0, y: 0, behavior }) })
Tej samej zasady można użyć do wykrycia, czy zaimplementować bogate w ruch interfejsy użytkownika z bibliotekami JS — czy nawet same ładować biblioteki.
W poniższym fragmencie kodu funkcja powraca wcześnie, jeśli użytkownik woli ograniczony ruch, unikając niepotrzebnego importu dużej zależności — korzyści dla użytkownika. Jeśli nie mają ustawionych preferencji ruchu, możemy dynamicznie zaimportować bibliotekę animacji Greensock i zainicjować nasze animacje.
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)') const loadGSAPAndInitAnimations = () => { /* If user prefers reduced motion, do nothing */ if (prefersReducedMotion.matches) return /* Otherwise, import the GSAP module and initialize animations */ import('gsap').then((object) => { const gsap = object.default /* Initialize animations with GSAP here */ }) } loadGSAPAndInitAnimations()
reduced-motion
nie oznacza braku ruchu
Podczas stylizacji pod kątem ograniczonych preferencji ruchu ważne jest, abyśmy nadal zapewniali użytkownikowi zrozumiałe i przystępne wskaźniki , kiedy dana czynność została wykonana. Na przykład, wyłączając rozpraszający lub intensywnie poruszający się stan najechania dla użytkowników, którzy preferują ograniczony ruch, musimy zadbać o zapewnienie jasnego alternatywnego stylu, gdy użytkownik najedzie na element.
Poniższa prezentacja przedstawia skomplikowane przejście, gdy użytkownik najedzie kursorem na element galerii lub skupi się na nim, jeśli nie ma ustawionych preferencji ruchu. Jeśli preferują zredukowany ruch, przejście jest bardziej subtelne, ale nadal wyraźnie wskazuje stan najechania:
Zredukowany ruch nie musi też oznaczać usunięcia wszystkich przekształceń z naszej strony internetowej. Na przykład przycisk, który ma małą ikonę strzałki, która przesuwa się o kilka pikseli po najechaniu kursorem, prawdopodobnie nie spowoduje problemów dla kogoś, kto preferuje ograniczone ruchy, i jest bardziej użytecznym wskaźnikiem zmiany stanu niż sam kolor.
Czasami widzę, jak programiści stosują zredukowane style ruchu w następujący sposób, co eliminuje wszystkie przejścia i animacje na wszystkich elementach:
@media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } }
Jest to prawdopodobnie lepsze niż ignorowanie preferencji ruchu użytkowników, ale nie pozwala nam łatwo dostosować elementów, aby zapewnić bardziej subtelne przejścia, gdy jest to konieczne.
W poniższym fragmencie kodu mamy przycisk, którego skala rośnie po najechaniu myszą . Zmieniamy kolory i skalę, ale użytkownicy preferujący ograniczenie ruchu w ogóle nie otrzymają przejścia:
button { background-color: hotpink; transition: color 300ms, background-color 300ms, transform 500ms cubic-bezier(.44, .23, .47, 1.27); } button:hover, button:focus { background-color: darkviolet; color: white; transform: scale(1.2); } @media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } button { /* Even though we would still like to transition the colors of our button, the following rule will have no effect */ transition: color 200ms, background-color 200ms; } button:hover, button:focus { /* Preventing the button scaling on hover */ transform: scale(1); } }
Sprawdź to demo, aby zobaczyć efekt. Być może nie jest to idealne rozwiązanie, ponieważ nagła zmiana koloru bez przejścia może wydawać się bardziej wstrząsająca niż przejście trwające kilkaset milisekund. Jest to jeden z powodów, dla których generalnie wolę stylizować na zredukowany ruch w każdym przypadku z osobna.
Jeśli jesteś zainteresowany, to jest to samo demo, które zostało zrefaktoryzowane, aby umożliwić dostosowanie przejścia w razie potrzeby. Używa niestandardowej właściwości dla czasu trwania przejścia, co pozwala nam włączać i wyłączać przejście skali bez konieczności przepisywania całej deklaracji.
Kiedy usuwanie animacji jest lepsze
Eric Bailey w swoim artykule podkreśla, że „nie każde urządzenie, które ma dostęp do sieci, może renderować animację lub renderować animację płynnie” W przypadku urządzeń z niską częstotliwością odświeżania, które mogą powodować niestabilne animacje, w rzeczywistości może być lepiej usunąć animację . Funkcji update
nośnika można użyć do ustalenia tego:
@media screen and (prefers-reduced-motion: reduce), (update: slow) { * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }
Koniecznie przeczytaj cały artykuł, aby uzyskać rekomendacje Erica, ponieważ jest on pierwszorzędną osobą w dziedzinie dostępności.
Suma wszystkich części
Ważne jest, aby pamiętać o ogólnym projekcie strony, skupiając się tak mocno na CSS na poziomie komponentów. To, co może wydawać się dość nieszkodliwą animacją na poziomie komponentu, może mieć znacznie większy wpływ, gdy jest powtarzane na całej stronie i jest jedną z wielu ruchomych części.
W artykule Tatiany sugeruje zorganizowanie animacji (z prefers-reduced-motion
) w pojedynczym pliku CSS, który można załadować tylko wtedy, gdy (prefers-reduced-motion: no-preference)
oceni prawdę. Oglądanie sumy wszystkich naszych animacji może mieć dodatkową zaletę, pomagając nam zwizualizować wrażenia związane z odwiedzaniem witryny jako całości i odpowiednio dostosować nasze style ograniczonego ruchu.
Wyraźny przełącznik ruchu
Chociaż prefers-reduced-motion
jest przydatne, ma wadę polegającą na tym, że obsługuje tylko użytkowników, którzy są świadomi funkcji w ustawieniach systemu. Wielu użytkowników nie zna tego ustawienia, podczas gdy inni mogą korzystać z pożyczonego komputera bez dostępu do ustawień na poziomie systemu. Mimo to inni mogą być zadowoleni z ruchu w większości witryn, ale uważają, że witryny z dużym wykorzystaniem ruchu są trudne do zniesienia.
To może być denerwujące, gdy trzeba dostosować preferencje systemowe tylko po to, aby odwiedzić jedną witrynę. Z tych powodów w niektórych przypadkach może być preferowane udostępnienie w samej witrynie wyraźnej kontrolki do włączania i wyłączania ruchu . Możemy to zaimplementować za pomocą JS.
Poniższe demo ma kilka kręgów dryfujących w tle. Początkowe style animacji są określane przez preferencje systemowe użytkownika (z prefers-reduced-motion
), jednak użytkownik ma możliwość włączania i wyłączania ruchu za pomocą przycisku. Dodaje to do body
klasę, której możemy użyć do ustawienia stylów w zależności od wybranych preferencji. Jako bonus, wybór preferencji ruchu jest również zachowywany w pamięci lokalnej — jest więc „zapamiętywany” przy następnej wizycie użytkownika.
Właściwości niestandardowe
Jedną z funkcji w wersji demonstracyjnej jest to, że przełącznik ustawia niestandardową właściwość --playState
, której możemy użyć do odtwarzania lub wstrzymywania animacji. Może to być szczególnie przydatne, jeśli musisz wstrzymać lub odtworzyć kilka animacji jednocześnie. Przede wszystkim ustawiamy stan odtwarzania na paused
:
.circle { animation-play-state: var(--playState, paused); }
Jeśli użytkownik ustawił preferencje dotyczące ograniczonego ruchu w ustawieniach systemu, możemy ustawić stan odtwarzania na running
:
@media (prefers-reduced-motion: no-preference) { body { --playState: running; } }
Uwaga: Ustawienie tego na body
, w przeciwieństwie do pojedynczego elementu, oznacza, że właściwość niestandardowa może być dziedziczona.
Gdy użytkownik kliknie przełącznik, właściwość niestandardowa zostanie zaktualizowana w body
, co spowoduje przełączenie wszystkich wystąpień, w których jest używana:
// This will pause all animations that use the `--playState` custom property document.body.style.setProperty('--playState', 'paused')
Może to nie być idealne rozwiązanie we wszystkich przypadkach, ale jedną z zalet jest to, że animacja po prostu zatrzymuje się, gdy użytkownik kliknie przełącznik, zamiast wracać do stanu początkowego, co może być dość niepokojące.
Specjalne podziękowania należą się Scottowi O'Hara za jego zalecenia dotyczące poprawy dostępności przełącznika. Uświadomił mi, że niektóre czytniki ekranu nie ogłaszają zaktualizowanego tekstu przycisku, który zmienia się, gdy użytkownik kliknie przycisk, i zamiast tego sugerują role="switch"
na przycisku, z on
lub off
aria-checked
po kliknięciu.
Komponent wideo
W niektórych przypadkach lepszym rozwiązaniem może być przełączanie ruchu na poziomie komponentu. Weź stronę internetową z automatycznie odtwarzanym tłem wideo. Powinniśmy zadbać o to, aby film nie odtwarzał się automatycznie w przypadku użytkowników preferujących ograniczenie ruchu, ale nadal powinniśmy zapewnić im możliwość odtwarzania filmu tylko wtedy , gdy wybiorą . (Niektórzy mogą argumentować, że powinniśmy unikać automatycznego odtwarzania filmów, ale nie zawsze wygrywamy tę bitwę!) Podobnie, jeśli film jest ustawiony na automatyczne odtwarzanie dla użytkowników bez określonych preferencji, powinniśmy również zapewnić im sposób na wstrzymać wideo.
To demo pokazuje, jak możemy ustawić atrybut autoodtwarzania , gdy użytkownik nie ma określonej preferencji ruchu, implementując niestandardowy przycisk odtwarzania/wstrzymania, aby umożliwić mu również przełączanie odtwarzania, niezależnie od preferencji:
(Później natknąłem się na ten post autorstwa Scotta O'Hary, opisujący dokładnie ten przypadek użycia.)
Używanie elementu <picture>
Chris Coyier napisał interesujący artykuł łączący kilka technik ładowania różnych źródeł mediów w zależności od preferencji ruchu użytkownika. To całkiem fajne, ponieważ oznacza to, że dla użytkowników preferujących zmniejszony ruch , znacznie większy plik GIF nawet nie zostanie pobrany. Minusem, o ile widzę, jest to, że po pobraniu pliku użytkownik nie ma możliwości powrotu do alternatywy bez ruchu.
Tworzę zmodyfikowaną wersję demo, która dodaje tę opcję. (Włącz reduced-motion
w preferencjach systemowych, aby zobaczyć go w akcji.) Niestety, podczas przełączania między animowanymi i wolnymi od ruchu opcjami w Chrome wydaje się, że plik GIF jest pobierany od nowa za każdym razem, co nie ma miejsca w przypadku innych przeglądarek:
Mimo to ta technika wydaje się być bardziej szanowanym sposobem wyświetlania GIF-ów, co może być źródłem frustracji użytkowników.
Wsparcie dla przeglądarek i końcowe przemyślenia
prefers-reduced-motion
ma doskonałe wsparcie we wszystkich nowoczesnych przeglądarkach od kilku lat. Jak widzieliśmy, stosując podejście polegające na ograniczeniu ruchu w pierwszej kolejności, przeglądarki nieobsługujące ruchu uzyskają po prostu awaryjną reduced-motion
. Nie ma powodu, aby nie używać go dzisiaj, aby uczynić swoje witryny bardziej dostępnymi.
Niestandardowe przełączniki zdecydowanie mają swoje miejsce i mogą znacznie poprawić wrażenia użytkowników, którzy nie są świadomi tego ustawienia lub tego, co ono robi. Minusem dla użytkownika jest niespójność — jeśli każdy programista jest zmuszony wymyślić własne rozwiązanie, użytkownik musi poszukać przełącznika ruchu w innym miejscu na każdej stronie.
Wydaje się, że brakującą warstwą są tutaj przeglądarki . Chciałbym, aby przeglądarki wdrażały przełączniki reduced-motion
, w miejscu łatwo dostępnym dla użytkownika, aby ludzie wiedzieli, gdzie je znaleźć, niezależnie od przeglądanej witryny. Może to zachęcić programistów do poświęcenia większej ilości czasu na zapewnienie dostępności ruchu.
Powiązane zasoby
- Specyfikacja zapytań o media poziomu 5, World Wide Web Consortium (W3C)
-
prefers-reduced-motion
, MDN Web Docs, Mozilla - Konstrukcja ze zredukowanym ruchem dla czułości ruchu, Val Head, Smashing Magazine
- Podejście do animacji bez ruchu, Tatiana Mac
- Zredukowana technika filmowa, Take 2, Chris Coyier, CSS-Tricks
- Ponowne odwiedzanie prefers
prefers-reduced-motion
, The Reduced Motion Media Query, Eric Bailey, CSS-Tricks - Ograniczanie ruchu w celu poprawy dostępności, Lindsey Kopacz