Медиа-запрос для устройств, поддерживающих зависание
Я хотел бы предоставить отдельное поведение для браузеров, поддерживающих зависание (например, настольных браузеров), а также те, которые не работают (например, сенсорные устройства). В частности, я хочу объявить состояние зависания в браузерах, которые его поддерживают, но не для браузеров, которые этого не делают, чтобы избежать того, чтобы мобильные браузеры эмулировали его с помощью дополнительных кранов, так как это нарушает другие взаимодействия на странице - не определяя зависание для этих браузеров это можно избежать.
Я прочитал в функцию Interaction Media Queries, и похоже, что это должно сделать трюк. Я бы мог сделать что-то вроде:
@media (hover: none) {
/* behaviour for touch browsers */
}
В соответствии с CanIUse он доступен во всех браузерах, которые мне нужны для поддержки, кроме IE11 и Firefox.
Итак, я подумал, могу ли я сделать это наоборот - поскольку основные сенсорные устройства поддерживают его, а затем отрицают это:
@media not (hover: none) {
/* behaviour for desktop browsers */
}
Однако это не работает вообще.
Пример псевдокода того, что я пытаюсь сделать:
.myelement {
/* some styling */
/* note: no hover state here */
}
@media(this device supports hover) {
.myelement:hover {
/* more styling */
}
}
Итак, есть ли способ сделать эту работу таким образом, или я ошибаюсь?
Ответы
Ответ 1
Благодаря комментариям Dekel я решил это, выполнив логику в JS и вместо этого применив класс:
например.
const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
document.body.classList.add('can-hover');
}
Затем в таблице стилей:
.myElement {
background: blue;
}
.can-hover .myElement:hover {
background: red;
}
Я тестировал это на настольных компьютерах Chrome, Safari и Firefox, а также на iOS Safari и работает как ожидалось.
Ответ 2
not
должен префикс типа носителя (экран, печать, все и т.д.), а не средство массовой информации (наведение, точка и т.д.).
Неправильно:
@media not (hover: none)
Правильно:
@media not all and (hover: none)
Да, его неинтуитивный и странный. Источник (см. комментарии).
Таким образом, вам не нужен javascript для альтернативного результата медиа-запроса.
Ответ 3
Из спецификаций:
none
Указывает, что основная система указателей не может наводиться, или нет системы указателей. Примеры включают сенсорные экраны и экраны, в которых используется стилус для рисования.
Указательные системы, которые могут зависать, но для которых это неудобно, а не являются частью обычного способа их использования, также соответствуют этому значению.
Например, сенсорный экран, в котором длительное нажатие обрабатывается как зависание, будет соответствовать зависанию: none.
Если ваш браузер (мобильный/сенсорный) поддерживает длительное нажатие для имитации наведения, использование hover: none
не будет работать. Вы можете просто использовать значение по умолчанию и переопределить его (с приоритетом по умолчанию css):
body {
background: red;
}
@media (hover: hover) {
body {
background: blue;
}
}
Рабочий стол будет иметь фон blue
, а для мобильного /touch будет red
фон
Проверьте следующий пример:
https://jsfiddle.net/mcy60pvt/1/
Чтобы проверить возможность длительного нажатия на мобильник, вы можете использовать этот пример:
https://jsfiddle.net/mcy60pvt/3/
В приведенном выше примере зеленый блок имеет определение :hover
для рабочего стола и мобильного устройства, однако для рабочего стола фон будет меняться на yellow
, а для мобильных устройств (с длинным нажатием) он изменится на white
.
Вот пример css для последнего примера:
body {
background: red;
}
div.do-hover {
border: 1px solid black;
width: 250px;
height: 250px;
background: green;
}
div.do-hover:hover {
background: white;
}
@media (hover: hover) {
body {
background: blue;
}
div.do-hover:hover {
background: yellow;
}
}
В этом примере - браузеры, которые не поддерживают :hover
, будут просматривать окно hover me с зеленым фоном, а во время "наведения" (касание/длительное нажатие) - фон изменится на белый.
Обновление
Что касается добавленного псевдокода:
.myelement {
/* some styling #1 */
/* note: no hover state here */
}
@media(hover: hover) {
.myelement {
/* some styling that override #1 styling in case this browser suppot the hover*/
}
.myelement:hover {
/* what to do when hover */
}
}
Ответ 4
В соответствии с ответом Артина мы можем обращаться только к устройствам, которые поддерживают наведение с чистым css, с @media not all and (hover: none)
. Это выглядит странно, но оно работает.
Я сделал из него смесь Sass для упрощения использования:
@mixin hover-supported {
@media not all and (hover: none) {
&:hover {
@content;
}
}
}
Ниже будет изменен фоновый цвет .container
от красного до синего при наведении на устройства, поддерживающие наведение, без изменений для сенсорных устройств:
.container {
background-color: red;
@include hover-supported() {
background-color: blue;
}
}
Ответ 5
Для поддержки Firefox (см. Https://bugzilla.mozilla.org/show_bug.cgi?id=1035774) вам необходимо дважды написать некоторые правила. Обратите внимание, хотя в вопросе я не указал pointer: coarse
если предположить, что целью этих правил является нацеливание на мобильные экраны:
/* BEGIN devices that DON'T pinch/zoom */
/* If https://bugzilla.mozilla.org/show_bug.cgi?id=1035774
is fixed then we can wrap this section in a ...
@media not all and (pointer: coarse) and (hover: none) {
.. and do away with the 'NEGATE' items below */
.myelement {
/* some styling that you want to be desktop only (style as an anchor on desktop) */
font-size: 14px;
text-decoration: underline;
border: none;
}
/* END devices that DON'T pinch/zoom */
/* BEGIN devices that DO pinch/zoom */
@media (pointer: coarse) and (hover: none) {
.myelement {
/* style as a large button on mobile */
font-size: inherit; /* maintain e.g. larger mobile font size */
text-decoration: none; /* NEGATE */
border: 1px solid grey;
}
.myelement:hover {
/* hover-only styling */
}
}
/* END devices that DO pinch/zoom */
Комбинация (pointer: coarse) and (hover: none)
должна стать более полезной для целевых мобильных устройств, так как мобильные экраны становятся больше, и мы теряем корреляцию между размерами в пикселях и между мобильным и настольным компьютерами (уже в том случае, когда вы хотите различать планшет и рабочий стол)
Ответ 6
Вы можете использовать этот миксин Sass для стилизации наведения, он будет использовать рекомендованную замену :active
для сенсорных устройств. Работает во всех современных браузерах и IE11.
/**
Hover styling for all devices and browsers
*/
@mixin hover() {
@media (hover: none) {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
&:active {
@content;
}
}
@media (hover: hover), all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
&:hover {
@content;
}
}
}
.element {
@include hover {
background: red;
}
}