css - Медиа-запрос для устройств, поддерживающих зависание




hover media-queries (4)

Благодаря комментариям Декеля я решил эту проблему, запустив логику в 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, и он работает, как и ожидалось.

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

Я ознакомился с функцией 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 */
  }
}

Итак, есть ли способ сделать эту работу так, как задумано, или я ошибаюсь?


Для поддержки Firefox (см. 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) должна стать более полезной для целевых мобильных устройств, поскольку мобильные экраны становятся больше, и мы теряем корреляцию между размерами в пикселях и между мобильным и настольным компьютерами (уже в том случае, когда вы хотите различать планшет и рабочий стол)


Согласно ответу Артина, мы можем адресовать только те устройства, которые поддерживают hover с чистым 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;
    }
}

not следует указывать префикс типа носителя (экран, печать, все и т. д.), а не функцию носителя (указатель, точка и т. д.).

Неправильно:

@media not (hover: none)

Правильный:

@media not all and (hover: none)

Да, это не интуитивно и странно. Источник (см. Комментарии) .

Таким образом, вам не нужен JavaScript, чтобы чередовать результат медиа-запроса.





interaction-media-features