Приветствую. Представляю вашему вниманию перевод заметки «Detecting Hover-Capable Devices», опубликованной 30 июня 2021 года автором Michelle Barker

К сожалению, поискать на Habr более ранние материалы на аналогичную тему я додумался лишь после публикации. Нашёл качественную статью "Выявление устройств с сенсорными экранами на чистом CSS". А текущую заметку предлагаю считать дополнительным напоминанием о существовании технологии и повторением пройденного.

Сейчас, когда количество устройств стало бо́льшим, чем когда-либо прежде, мы, разработчики, больше не можем полагаться на область видимости, как единственный фактор, определяющий стилизацию сайта. До недавнего времени мы могли отталкиваться от размера устройства: например, считая, что на мобильных устройствах используется сенсорный ввод, а на устройствах с большим экраном — мышь. И на этом основании с помощь медиазапроса определить вариант стилизации содержимого:

.some-component {
  /* Styles for touch devices */
}

@media screen and (min-width: 1024px) {
  .some-component {
    /* Styles for hover-able devices */
  }
}

Но на сегодняшний день это не очень-то помогает. В современном IPad разрешение экрана может быть больше, чем у бюджетного ноутбука. Или, например, кто-то может использовать свой планшет как дополнительный монитор — имея в этом случае возможность наводить указатель на элементы. Но в приведённых выше медиазапросах устройства ввода никак не учитываются.

В наши дни к определению устройства пользователя нужно подходить более тщательно. К счастью, некоторые новые медиазапросы служат как раз для этой цели.

Медиазапросы 5 уровня

Помимо уже знакомых медиазапросов, позволяющих определять размер области видимости, спецификация CSS Level 5 Media Queries привнесла новые. Один из них позволяет определить, поддерживает ли основное указывающее устройство пользователя возмжоность наведения (hover). Допустимым является значение hover (будет true для таких устройств, как, например, мышь) и значение none (будет true для планшетов с сенсорными экранами). Использовать данный медиазапрос мы можем следующим образом:

.some-component {
  /* Styles for touch devices */
}

@media (hover: hover) {
  .some-component {
    /* Styles for hover-able devices */
  }
}

Уточнение: На самом деле, функционал hover и pointer является частью спецификации медиазапросов ещё с 4 уровня. Но лишь недавно стали поддерживаться почти всеми браузерами.

Данный пример корректно работает в большинстве браузеров, за исключением некоторых версий Android, которые имеют функционал, позволяющий имитировать hover долгим нажатием, из-за чего такие устройства могут быть распознаны как поддерживающие наведение. Если мы хотим показывать этим пользователям те же стили, что и на других сенсорных устройствах, нужно сделать дополнительный запрос.

Pointer

Функционал pointer проверяет наличие и точность указывающего устройства. Допустимыми являются значения coarse (для таких указателей, как палец при использовании устройств с сенсорным экраном), fine (например, для мыши) и none (устройство без указателя).

Добавление этого условия к нашему медиазапросу успешно определяет сенсорный ввод на Android-устройствах:

.some-component {
  /* Styles for touch devices, including Android */
}

@media (hover: hover) and (pointer: fine) {
  .some-component {
    /* Styles for hover-able devices */
  }
}

any-hover и any-pointer

Если перечисленного недостаточно, условия any-hover и any-pointer позволяют включать в проверку возможности не только основного, но и любого другого подключённого указывающего устройства. Следовательно, если у вас есть устройство с подключёнными и мышью и сенсорным экраном, запрос any-hover: hover будет true.

Мне пока что не приходилось применять данный функционал, но спецификация включает несколько примеров того, как он может использоваться.

Пример JavaScript

Недавно я сделал страничку с тремя одинаковыми изображениями, каждое из которых является ссылкой. При наведении курсора на эту ссылку-изображение, подобно всплывающей подсказке, показывается его имя. Но пользователи устройств с сенсорным экраном увидеть подсказку не смогут. Вместо этого, при нажатии сразу будет совершён переход по ссылке, что может раздражать, так как пользователи заранее не знают, куда именно попадут. Именно поэтому я решил при клике не осуществлять переход сразу, а лишь при нажатии на появившуюся дополнительную кнопку. Мы можем использовать тот же медиазапрос для определения устройства с сенсорным экраном в JS, используя matchMedia:

const list = document.querySelector('[data-list]')
const isHoverableDevice = window.matchMedia(
  '(hover: hover) and (pointer: fine)'
)

/* Hide the block link initially */
blockLink.hidden = true

list.addEventListener('click', (e) => {
  /* Do nothing if target is not a link, or device is hover-capable */
  if (!e.target.dataset.link || isHoverableDevice.matches) return

  /* If touch device, show the block link */
  e.preventDefault()
  blockLink.hidden = false
  blockLink.innerText = `Visit ${e.target.dataset.link}’s page`
  blockLink.setAttribute('href', e.target.href)
})

Результат:

Доступность

В зависимости от интерфейса, мы можем помочь вспомогательным технологиям, используя атрибуты ARIA, чтобы объявить кнопку, когда произойдут изменения, или переместить на кнопку внимание пользователя. Данный пример с MDN включает демонстрацию того, как использовать ARIA Live Regions для объявления динамических изменений элемента.

Поддержка браузерами

Отличная новость в том, что вы можете использовать эти медиазапросы уже сейчас, поскольку они поддерживаются всеми современными браузерами. Теперь вы можете улучшить удобство для пользователей любых устройств.

Комментарии (0)