Уважение предпочтений пользователей в отношении движения
Опубликовано: 2022-03-10prefers-reduced-motion
имеет отличную поддержку во всех современных браузерах пару лет назад. В этой статье Мишель Баркер объясняет, почему нет причин не использовать его сегодня, чтобы сделать ваши сайты более доступными.При работе с движением в Интернете важно учитывать, что не все воспринимают его одинаково. То, что может показаться гладким и гладким для одних, может раздражать или отвлекать других или, что еще хуже, вызывать чувство тошноты или даже вызывать припадки. Веб-сайты с большим количеством движений также могут оказывать более сильное влияние на время автономной работы мобильных устройств или вызывать использование большего объема данных (например, для автоматического воспроизведения видео потребуется больше данных пользователя, чем для статического изображения). Это лишь некоторые из причин, по которым сайты с большим количеством движений могут быть нежелательны для всех.
Большинство новых операционных систем позволяют пользователю устанавливать свои предпочтения движения в настройках на уровне системы. Медиа-запрос prefers-reduced-motion
(часть спецификации медиа-запросов уровня 5) позволяет нам определять предпочтения пользователей в отношении движения на системном уровне и применять стили CSS, соответствующие этому.
Два варианта для prefers-reduced-motion
: reduce
или no-preference
. Мы можем использовать его следующим образом в нашем CSS, чтобы отключить анимацию элемента, если пользователь явно установил предпочтение для уменьшения движения :
.some-element { animation: bounce 1200ms; } @media (prefers-reduced-motion: reduce) { .some-element { animation: none; } }
И наоборот, мы могли бы установить анимацию только в том случае, если у пользователя нет предпочтения движения. Преимущество этого заключается в уменьшении объема кода, который нам нужно написать, и означает, что меньше вероятность того, что мы забудем учесть предпочтения пользователей в отношении движения:
@media (prefers-reduced-motion: no-preference) { .some-element { animation: bounce 1200ms; } }
Дополнительным преимуществом является то, что старые браузеры, которые не поддерживают prefers-reduced-motion
, будут игнорировать правило и отображать только наш оригинальный элемент без движения.
Какое правило?
В отличие от медиа-запросов min-width
и max-width
, где более или менее сложился консенсус в отношении мобильных устройств (поэтому предпочтение отдается min-width
), не существует единого «правильного» способа написать ваши стили с уменьшенным движением. Я предпочитаю второй пример (применение анимации только в том случае, если prefers-reduced-motion: no-preference
оценивается как истинное) по причинам, перечисленным выше. Татьяна Мак написала эту прекрасную статью, в которой рассказывается о некоторых подходах, которые разработчики могут рассмотреть, а также о множестве других замечательных моментов, в том числе о ключевых вопросах, которые следует задать при разработке дизайна с использованием движения в Интернете.
Как всегда, общение в команде и последовательная стратегия являются ключом к тому, чтобы обеспечить охват всех основ, когда речь идет о веб-доступности.
Практическое использование: применение prefers-reduced-motion
к поведению прокрутки
prefers-reduced-motion
имеет множество применений помимо применения (или неприменения) анимации ключевых кадров или переходов. Одним из примеров является плавная прокрутка. Если мы установим scroll-behaviour: smooth
для нашего html
-элемента, когда пользователь щелкнет якорную ссылку на странице, он будет плавно прокручиваться до соответствующей позиции на странице (в настоящее время не поддерживается в Safari ):
html { scroll-behavior: smooth; }
К сожалению, в CSS у нас сейчас нет особого контроля над этим поведением. Если у нас есть длинная страница контента, страница прокручивается очень быстро, что может быть довольно неприятным для человека с чувствительностью к движению. Обернув его в медиа-запрос, мы можем предотвратить применение этого поведения в случаях, когда пользователь предпочитает reduced-motion
:
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
Обеспечение предпочтений движения в Javascript
Иногда нам нужно применить движение в JavaScript, а не в CSS. Точно так же мы можем определить предпочтения пользователя в движении с помощью JS, используя matchMedia
. Давайте посмотрим, как мы можем условно реализовать поведение плавной прокрутки в нашем коде 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 }) })
Тот же принцип можно использовать для определения того, следует ли реализовывать пользовательские интерфейсы с большим количеством движений с библиотеками JS или даже загружать сами библиотеки.
В следующем фрагменте кода функция возвращается раньше, если пользователь предпочитает уменьшить движение, избегая ненужного импорта большой зависимости — выигрыш в производительности для пользователя. Если для них не заданы предпочтения движения, мы можем динамически импортировать библиотеку анимации Greensock и инициализировать нашу анимацию.
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
не означает отсутствие движения
При настройке стиля для уменьшения движения важно, чтобы мы по-прежнему предоставляли пользователю значимые и доступные индикаторы того, когда произошло действие. Например, при отключении отвлекающего или интенсивного движения наведения для пользователей, предпочитающих уменьшенное движение, мы должны позаботиться о том, чтобы предоставить четкий альтернативный стиль, когда пользователь наводит курсор на элемент.
Следующая демонстрация показывает сложный переход, когда пользователь наводит курсор или фокусируется на элементе галереи, если у него не заданы предпочтения движения. Если они предпочитают уменьшенное движение, переход будет более тонким, но все же четко указывает на состояние зависания:
Уменьшение движения не обязательно означает удаление всех преобразований с нашей веб-страницы. Например, кнопка со значком маленькой стрелки, которая перемещается на несколько пикселей при наведении, вряд ли вызовет проблемы у тех, кто предпочитает работу с уменьшенным движением, и обеспечивает более полезный индикатор изменения состояния , чем один только цвет.
Иногда я вижу, как разработчики применяют уменьшенные стили движения следующим образом, что устраняет все переходы и анимацию для всех элементов:
@media screen and (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; scroll-behavior: auto !important; } }
Это, возможно, лучше, чем игнорирование предпочтений пользователей в движении, но не позволяет нам легко настраивать элементы для обеспечения более тонких переходов, когда это необходимо.
В следующем фрагменте кода у нас есть кнопка, масштаб которой увеличивается при наведении курсора . Мы изменяем цвета и масштаб, но пользователи, предпочитающие уменьшение движения, вообще не получат перехода:
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); } }
Посмотрите это демо, чтобы увидеть эффект. Это, возможно, не идеально, так как внезапное переключение цвета без перехода может показаться более неприятным, чем переход на пару сотен миллисекунд. Это одна из причин, почему в целом я предпочитаю стиль для уменьшения движения в каждом конкретном случае.
Если вам интересно, это та же демонстрация, переработанная, чтобы при необходимости можно было настроить переход. Он использует пользовательское свойство длительности перехода, что позволяет нам включать и выключать переход масштаба без необходимости переписывать все объявление.
Когда лучше удалить анимацию
Эрик Бэйли подчеркивает, что «не каждое устройство, имеющее доступ к Интернету, также может воспроизводить анимацию или воспроизводить анимацию плавно» в своей статье «Пересмотр предпочтений с уменьшенным движением, медиа-запрос с уменьшенным движением». Для устройств с низкой частотой обновления, которая может вызывать дерганую анимацию, на самом деле может быть предпочтительнее удалить анимацию . Чтобы определить это, можно использовать функцию update
носителя:
@media screen and (prefers-reduced-motion: reduce), (update: slow) { * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; } }
Обязательно прочитайте полную статью, чтобы узнать о рекомендациях Эрика, так как он первоклассный человек, которому нужно следовать в области специальных возможностей.
Сумма всех частей
Важно помнить об общем дизайне страницы, когда так сильно сосредотачиваетесь на CSS на уровне компонентов. То, что может показаться довольно безобидной анимацией на уровне компонентов, может иметь гораздо большее влияние, когда оно повторяется по всей странице и является одной из многих движущихся частей.
В статье Татьяны она предлагает организовать анимацию (с prefers-reduced-motion
) в один файл CSS, который может быть загружен только в том случае, если (prefers-reduced-motion: no-preference)
значение true. Просмотр общей суммы всех наших анимаций может иметь дополнительное преимущество, помогая нам визуализировать опыт посещения сайта в целом и соответствующим образом адаптировать стили с уменьшенным движением.
Явное переключение движения
Хотя prefers-reduced-motion
полезен, у него есть недостаток, заключающийся в том, что он предназначен только для пользователей, которые знают об этой функции в настройках своей системы. Многие пользователи не знают об этом параметре, в то время как другие могут использовать заимствованный компьютер без доступа к настройкам на уровне системы. Тем не менее, другие могут быть довольны движением на подавляющем большинстве сайтов, но считают, что сайты с интенсивным использованием движения трудно переносить.
Может раздражать необходимость настраивать системные настройки только для посещения одного сайта. По этим причинам в некоторых случаях может быть предпочтительнее предоставить явный элемент управления на самом сайте для включения и выключения движения . Мы можем реализовать это с помощью JS.
В следующей демонстрации есть несколько кругов, дрейфующих по фону. Первоначальные стили анимации определяются системными настройками пользователя (с помощью preferences prefers-reduced-motion
), однако у пользователя есть возможность включать или выключать движение с помощью кнопки. Это добавляет к body
класс, который мы можем использовать для установки стилей в зависимости от выбранного предпочтения. В качестве бонуса выбор предпочтения движения также сохраняется в локальном хранилище, поэтому он «запоминается» при следующем посещении пользователем.
Пользовательские свойства
Одной из особенностей демонстрации является то, что переключатель устанавливает пользовательское свойство --playState
, которое мы можем использовать для воспроизведения или приостановки анимации. Это может быть особенно удобно, если вам нужно приостановить или воспроизвести несколько анимаций одновременно. Прежде всего, мы устанавливаем состояние воспроизведения на paused
:
.circle { animation-play-state: var(--playState, paused); }
Если пользователь установил предпочтение уменьшенного движения в своих системных настройках, мы можем установить состояние воспроизведения в running
:
@media (prefers-reduced-motion: no-preference) { body { --playState: running; } }
Примечание. Установка этого значения для body
, а не для отдельного элемента, означает, что пользовательское свойство может быть унаследовано.
Когда пользователь нажимает на переключатель, в body
обновляется пользовательское свойство, которое переключает все экземпляры, в которых оно используется:
// This will pause all animations that use the `--playState` custom property document.body.style.setProperty('--playState', 'paused')
Это может быть не идеальным решением во всех случаях, но одним из преимуществ является то, что анимация просто приостанавливается , когда пользователь нажимает на переключатель, а не возвращается в исходное состояние, что может быть довольно резким.
Особая благодарность Скотту О'Хара за его рекомендации по улучшению доступности переключателя. Он сообщил мне, что некоторые программы для чтения с экрана не сообщают об обновленном тексте кнопки, который изменяется, когда пользователь нажимает кнопку, и вместо этого предложил для кнопки role="switch"
с on
или off
aria-checked
при нажатии.
Видео компонент
В некоторых случаях переключение движения на уровне компонентов может быть лучшим вариантом. Возьмите веб-страницу с автоматически воспроизводимым фоновым видео. Мы должны гарантировать, что видео не воспроизводится автоматически для пользователей, предпочитающих уменьшенное движение, но мы все же должны предоставить им возможность воспроизводить видео, только если они выберут . (Некоторые могут возразить, что нам следует избегать автоматического воспроизведения видео с полной остановкой, но мы не всегда побеждаем в этой битве!) Аналогичным образом, если видео настроено на автоматическое воспроизведение для пользователей без заявленных предпочтений, мы также должны предоставить им способ приостановить видео.
Эта демонстрация показывает, как мы можем установить атрибут автозапуска, когда у пользователя нет заявленных предпочтений движения, реализуя пользовательскую кнопку воспроизведения/паузы, чтобы позволить им также переключать воспроизведение независимо от предпочтений:
(Впоследствии я наткнулся на этот пост Скотта О'Хара, подробно описывающий именно этот вариант использования.)
Использование элемента <picture>
Крис Койер написал интересную статью, в которой сочетает несколько методов загрузки различных медиа-источников в зависимости от предпочтений пользователя в отношении движения. Это довольно круто, так как это означает, что для пользователей, предпочитающих уменьшенное движение , GIF-файл гораздо большего размера даже не будет загружен. Недостатком, насколько я вижу, является то, что после загрузки файла у пользователя нет возможности вернуться к альтернативе без движения.
Я создаю модифицированную версию демо, которая добавляет эту опцию. (Включите режим с reduced-motion
в настройках системы, чтобы увидеть его в действии.) К сожалению, при переключении между параметрами с анимацией и без движения в Chrome кажется, что файл GIF каждый раз загружается заново, чего не происходит в другие браузеры:
Тем не менее, этот метод кажется более уважительным способом отображения GIF-файлов, который может быть источником разочарования для пользователей.
Поддержка браузера и заключительные мысли
prefers-reduced-motion
отлично поддерживается во всех современных браузерах пару лет назад. Как мы видели, при выборе подхода с уменьшенным движением в первую очередь браузеры, не поддерживающие его, просто получат запасной вариант с reduced-motion
. Нет причин не использовать его сегодня, чтобы сделать ваши сайты более доступными.
Пользовательские переключатели, безусловно, имеют место и могут значительно улучшить работу пользователей, которые не знают об этом параметре или о том, что он делает. Обратной стороной для пользователя является непоследовательность — если каждый разработчик вынужден придумывать свое собственное решение, пользователю нужно искать переключатель движения в разных местах на каждом веб-сайте.
Такое ощущение, что недостающий слой — это браузеры . Я бы хотел, чтобы браузеры реализовывали переключатели с reduced-motion
, где-то легко доступным для пользователя, чтобы люди знали, где его найти, независимо от того, какой сайт они просматривают. Это также может побудить разработчиков тратить больше времени на обеспечение доступности движения.
Связанные ресурсы
- Спецификация мультимедийных запросов уровня 5, Консорциум World Wide Web (W3C)
-
prefers-reduced-motion
, веб-документы MDN, Mozilla - Дизайн с уменьшенным движением для чувствительности к движению, Val Head, Smashing Magazine
- Применяя подход к анимации без движения, Татьяна Мак
- Техника уменьшенного кино, Дубль 2, Крис Койер, CSS-трюки
- Возвращаясь к
prefers-reduced-motion
, Медиа-запрос с уменьшенным движением, Эрик Бейли, CSS-трюки - Уменьшение движения для улучшения доступности, Линдси Копач