Ищем поддержку hover на css / Хабр
lipton_ice_teaВремя на прочтение 2 мин
Количество просмотров13K
CSS *HTML *
Доброго времени суток, дорогие хабрахабровцы!
При создании адаптивной версии сайта, часто бывают ситуации, когда надо знать: поддерживает ли браузер пользователя hover, или нет. К примеру, выпадающее при наведении подменю, или же различные анимации, привязанные к событию hover — все это нужно только на ПК. На touch-устройствах поведение элементов должно меняться. Так как же задать определенные стили только для устройств с поддержкой hover на css, не забывая о кроссбраузерности?
В начале сразу хочу сказать о том, что есть js-библиотека Modernizr, которая решает эту задачу. Но… Прикручивать эту библиотеку только для определения поддержки hover, вместо написания одного медиа-запроса в css — не лучший вариант, на мой взгляд.
Но и с медиа-запросами не все так просто. Давайте посмотрим, какие есть варианты!
1. media (hover)
div{color:red;}
@media (hover){
/*Поддерживает hover*/
div{color:green;}
}Данный медиа-запрос позволит отдельно прописывать стили только для устройств, с поддержкой hover. Но давайте посмотрим на поддержку браузерами: caniuse.com/#feat=css-media-interaction
Как видим, он не поддерживается IE и Firefox. Т.е. наш код будет воспринимать эти браузеры, как без поддержки hover. Такой вариант нам не подходит!
2. media (pointer:coarse)
div{color:green;}
@media (pointer:coarse){
/*touch-устройство*/
div{color:red;}
}Этот запрос работает в точности наоборот, т.е. только для touch-устройств. Поддержка такая же, как и у media (hover), но т.к. IE и Firefox являются браузерами для ПК — то в них и так не должен срабатывать данный медиа-запрос.
Такое решение вполне подходит для тех случаев, когда нужно прописать стили именно для touch-устройств.
Но в основном, стоит задача — прописать стили именно для hover. А это означает, что придется сначала писать стили для всех браузеров, а потом сбрасывать их в медиа-запросе. Это не только увеличивает код, но и довольно неудобно, т.к. надо дублировать каждое свойство, измененное при событии hover на элементе.
3. media (hover) +
Выбирая из двух вышеупомянутых вариантов, первый наиболее привлекательный. Была бы еще браузерная поддержка побольше…
Но, к счастью, у нас есть целый ряд медиа-запросов, которые поддерживаются только в определенных браузерах. Специфичность такой поддержки можно посмотреть на этом сайте.
Итак, данный код будет работать только в IE:
@media (min-width:0\0) {}А этот медиа-запрос сработает только для Firefox:
@media (min--moz-device-pixel-ratio:0) {}Так давайте же объединим все 3 запроса!
div{color:red;}
@media (hover) , (min-width:0\0) , (min--moz-device-pixel-ratio:0){
/*Поддерживает hover*/
div{color:green;}
}
В результате получаем универсальный медиа-запрос, срабатывающий при поддержке hover.
Запрос поддерживается во всех основных браузерах, и как бонус, корректно работает на Blackberry и в Opera Mini (чего не было во 2 варианте).
Демо сравнения 3х подходов. Зеленый цвет = поддержка hover:
Теги:
- sass
- css
- web
- html
- hover
- media queries
Хабы:
- CSS
- HTML
Обнаружение сенсорного ввода для touchscreen или hover для мыши
Ещё совсем недавно информации о размерах экрана было достаточно для предположения, например, что мобильные устройства будут использовать сенсорный ввод для touchscreen, а пользователи устройств с экраном большего размера, вероятнее всего, используют для управления курсором мышь. Разнообразие устройств с помощью которых можно просматривать веб-сайт не позволяет полагаться только на размеры области просмотра (viewport), как на фактор, определяющий выбор CSS и отдельное поведение страницы для touch-устройств.
Когда-то можно было спокойно обходиться только получением размеров экрана:
.some-component {
/* Устройства с сенсорным вводом */
}
@media screen and (min-width: 1024px) {
.some-component {
/* Вероятно тут будет работать hover */
/* Наверное, это устройство с мышью */
}
}Сегодня это уже не очень помогает. У хорошего планшета разрешение экрана может быть сильно выше, чем у недорогого ноутбука. А кто-то может подключить свой планшет в качестве дополнительного монитора и таким образом получить возможность использовать наведение курсора (hover) на элементы веб-страницы с помощью мыши.
Медиа-запрос из примера выше не несёт никакой полезной информации о способах ввода и управления курсором. Поэтому для определения, как пользователь просматривает сайт и какой тип устройства ввода использует, следует анализировать что-нибудь кроме размеров экрана. Для этого можно воспользоваться некоторыми новыми медиа-запросами.
Level 5 Media Queries
Спецификация CSS Level 5 Media Queries, помимо уже знакомых для определения размеров области просмотра, предоставляет набор новых медиа-запросов.
Один из них – hover feature поможет определить, есть ли у пользователя возможности наведения основного указателя на элементы страницы с помощью мыши.
Возможные для применения этого медиа-запроса значения: hover (для устройства с мышью) или none (например, для планшета или смартфона с сенсорным вводом).
Медиа-запрос hover можно использовать следующим образом:
.some-component {
/* Устройства с сенсорным вводом */
}
@media (hover: hover) {
.some-component {
/* Тут будет работать hover */
/* Это устройство с мышью */
}
}Функции
hoverиpointerна самом деле являются частью спецификации Level 4 Media Queries, но лишь недавно стали поддерживаться большинством браузеров.
Это всё хорошо работает в большинстве браузеров, но в некоторых версиях Android есть функция, при которой долгое нажатие имитирует наведение (hover) и тогда этот медиа-запрос вернёт true.
Чтобы предоставить этим пользователям те же стили, что и для других сенсорных устройств с touchscreen, следует обратиться к другой медиа-функции.
Pointer
Функция pointer проверяет, есть ли на устройстве указатель и точность указательного устройства. Возможные значения: (грубое для, например, пальца на сенсорном экране), fine (точное, например, мышь) или none (отсутствие, устройство без указателя).
Добавление проверки pointer в медиа-запрос успешно обнаруживает сенсорный ввод и на Android-устройствах:
.some-component {
/* Устройства с сенсорным вводом, в т.ч. Android */
}
@media (hover: hover) and (pointer: fine) {
.some-component {
/* Тут будет работать hover и pointer===fine */
/* Это устройство с мышью */
}
}See this code Hover and pointer media query on x.xhtml.ru.
any-hover и any-pointerПредыдущие методы использовали для определения основные устройства ввода.
Когда недостаточно определять сенсорный ввод только по основному устройству ввода, можно использовать в медиа-запросах функции any-hover и any-pointer, которые проверяют любой тип ввода.
Таким образом, если используется устройство, которое реагирует как на мышь, так и на сенсорный ввод, any-hover: hover будет возвращать true. Cпецификация включает несколько примеров того, как это (а также более сложные комбинации) можно использовать.
Пример для javascript

Этот же медиа-запрос для обнаружения сенсорного ввода можно использовать и в JS с помощью :
const list = document.querySelector('[data-list]')
const isHoverableDevice = window.matchMedia(
'(hover: hover) and (pointer: fine)'
)
const blockLink = document.querySelector('[data-button-link]')
/* сперва скроем blockLink */
blockLink.hidden = true
list.addEventListener('click', (e) => {
/* ничего не делаем, если target не ссылка, устройство не умеет hover */
if (!e.target.dataset.link || isHoverableDevice.matches) return
/* Если это сенсорный экран, перехватываем клик
показываем ссылку
*/
e.preventDefault()
blockLink.hidden = false
blockLink.innerText = `Visit ${e.target.dataset.link}’s page`
blockLink.setAttribute('href', e.target.href)
})Вот пример:
See this code Touch/hover tooltip on x.xhtml.ru.
Доступность
В зависимости от пользовательского интерфейса, возможно, понадобится задействовать вспомогательные технологии, используя ARIA-атрибуты для объявления кнопки, когда происходит изменение или перемещение фокуса на кнопку.
Этот пример из MDN демонстрирует, как использовать живые ARIA-регионы для объявления динамических изменений элемента.
Поддержка в браузерах
Эти медиа-запросы можно использовать прямо сейчас, поскольку они поддерживаются во всех современных браузерах и они помогут улучшить взаимодействие с пользователями всех устройств.
Detecting Hover-Capable Devices.
Как реализовать наведение мыши или наведение курсора в Vue
В CSS довольно легко что-то изменить при наведении наведения . Мы просто используем псевдокласс :hover :
.item {
фон: синий;
}
.item:наведите {
фон: зеленый;
} В Vue все немного сложнее, потому что у нас нет встроенной функциональности.
Большую часть этого приходится реализовывать самостоятельно.
Но не волнуйтесь, это не , что много работает.
Из этой короткой статьи вы узнаете:
- Как реализовать эффект наведения в Vue
- Как показать элемент при наведении курсора
- Как динамически обновлять классы при наведении курсора
- Как это сделать даже на пользовательских компонентах Vue
Прослушивание правильных событий
Итак, какие события нам нужно прослушивать?
Мы хотим знать, когда мышь находится над элементом.
Это можно выяснить, отслеживая, когда мышь входит в элемент, а когда мышь выходит из элемента.
Чтобы отслеживать, когда мышь уходит, мы будем использовать событие mouseleave.
Обнаружение входа мыши можно выполнить с помощью соответствующего события mouseenter, но мы не будем его использовать.
Причина в том, что могут возникнуть значительные проблемы с производительностью при использовании mouseenter на глубоких деревьях DOM. Это связано с тем, что mouseenter запускает уникальное событие для введенного элемента, а также для каждого отдельного элемента-предка.
Что мы будем использовать вместо этого, спросите вы?!?
Вместо этого мы будем использовать событие наведения мыши.
Событие mouseover работает почти так же, как mouseenter . Основное отличие состоит в том, что mouseover всплывают, как и большинство других событий DOM. Вместо того, чтобы создавать массу уникальных событий, есть только одно — сделать это намного быстрее!
Давайте все подключим
Чтобы все подключить, мы будем использовать события Vue, чтобы отслеживать, когда мышь входит и уходит, и соответственно обновлять наше состояние.
Мы также будем использовать сокращение v-on .
Вместо того, чтобы писать v-on:event , мы можем просто написать @event .
Вот как мы это подключаем:
<дел
@mouseover="наведение = истина"
@mouseleave="зависание = ложь"
/>
экспорт по умолчанию {
данные() {
возвращаться {
наведение: ложь,
};
}
} Теперь реактивное свойство hover всегда будет отражать, находится ли мышь над элементом или нет!
Отображение элемента при наведении
Если вы хотите показать элемент на основе состояния наведения, вы можете соединить это с директивой v-if:
<шаблон>
<дел>
<промежуток
@mouseover="наведение = истина"
@mouseleave="зависание = ложь"
>
Наведите меня, чтобы показать сообщение!
Это секретное сообщение.

актив {
фон: зеленый;
}
native="наведение = истина"
@mouseleave.native="зависание = ложь"
/>
шаблон>