web-dev-qa-db-fra.com

Requête multimédia pour les périphériques prenant en charge le survol

J'aimerais proposer un comportement distinct pour les navigateurs prenant en charge le survol (par exemple, les navigateurs de bureau) et ceux qui ne le font pas (par exemple, les appareils à écran tactile). Plus précisément, je veux déclarer un état de survol sur les navigateurs qui le prennent en charge, mais pas pour les navigateurs qui ne le font pas, afin d'éviter que les navigateurs mobiles ne l'émulent avec des tapotements supplémentaires, car cela rompt d'autres interactions sur la page - en ne définissant pas de survol Etat pour ces navigateurs cela est évité.

J'ai lu sur la fonctionnalité Interaction Media Queries et il semble bien que cela devrait suffire. Je serais capable de faire quelque chose comme:

@media (hover: none) {
  /* behaviour for touch browsers */
}

Selon CanIUse , il est disponible sur tous les navigateurs que je dois prendre en charge, sauf IE11 et Firefox.

Je me suis donc demandé si je pouvais le faire à l'inverse - étant donné que tous les périphériques tactiles principaux le supportent, alors annulez-le:

@media not (hover: none) {
  /* behaviour for desktop browsers */
}

Cependant, cela ne semble pas fonctionner du tout.

Pseudocode exemple de ce que j'essaie de faire:

.myelement {
  /* some styling */
  /* note: no hover state here */
}
@media(this device supports hover) {
  .myelement:hover {
    /* more styling */
  }
}

Alors, y at-il un moyen de faire ce travail de la manière prévue, ou suis-je sur la mauvaise voie?

18
moogal

Grâce aux commentaires de Dekel, j'ai résolu ce problème en exécutant la logique dans JS et en appliquant une classe:

par exemple.

const canHover = !(matchMedia('(hover: none)').matches);
if(canHover) {
  document.body.classList.add('can-hover');
}

Puis dans la feuille de style:

.myElement {
  background: blue;
}
.can-hover .myElement:hover {
  background: red;
}

J'ai testé cela sur les ordinateurs de bureau Chrome, Safari et Firefox, et iOS Safari, et tout se passe comme prévu.

7
moogal

not doit préfixer le type de support (écran, impression, tous, etc.) et non la fonctionnalité de support (survol, point, etc.).

Faux:

@media not (hover: none)

Correct:

@media not all and (hover: none)

Oui, c'est peu intuitif et bizarre. Source (voir commentaires) .

Donc, vous n'avez pas besoin de javascript pour alterner le résultat d'une requête multimédia.

27
artin

De la specs:

none 

Indique que le système de pointage principal ne peut pas survoler ou qu’il n’existe aucun système de pointage. Les exemples incluent les écrans tactiles et les écrans qui utilisent un stylet de dessin.
Les systèmes de pointage qui peuvent stationner, mais pour lesquels cela est incommode et ne fait pas partie de la façon dont ils sont utilisés, correspondent également à cette valeur. 

Par exemple, un écran tactile dans lequel une pression longue est traitée comme étant en survol correspondrait au survol: aucun.

Si votre navigateur (mobile/tactile) prend en charge l'appui long pour simuler le survol, l'utilisation de hover: none ne fonctionnera pas. Ce que vous pouvez faire, c'est simplement utiliser une valeur par défaut et la remplacer (avec la priorité css par défaut):

body {
    background: red;
}

@media (hover: hover) {
  body {
    background: blue;
  }
}

Bureau aura blue fond et mobile/touch aura red fond

Vérifiez l'exemple suivant:
https://jsfiddle.net/mcy60pvt/1/

Pour vérifier l’option appui long du mobile, vous pouvez utiliser cet exemple:
https://jsfiddle.net/mcy60pvt/3/

Dans l'exemple ci-dessus, le bloc vert a la définition :hover pour le bureau et le mobile. Toutefois, pour le bureau, l'arrière-plan passera à yellow et pour le mobile (avec un appui long), il deviendra white.

Voici le css pour le dernier exemple:

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;
  }
}

Dans cet exemple, les navigateurs qui ne prennent pas en charge :hover verront la zone survolez-moi avec un arrière-plan vert et pendant que vous la survolez (touchez/maintenez enfoncé), l'arrière-plan devient blanc.

mettre à jour

En ce qui concerne le pseudo-code ajouté:

.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 */
    }
}
11
Dekel

Selon la réponse d’Artin , nous ne pouvons traiter que les périphériques prenant en charge le survol en CSS pur, avec @media not all and (hover: none). Ça a l'air bizarre mais ça marche.

J'ai fait un mix Sass à partir de cela pour une utilisation plus facile:

@mixin hover-supported {
    @media not all and (hover: none) {
        &:hover {
            @content;
        }
    }
}

Ce qui suit changerait la couleur de fond de .container du rouge au bleu en survol pour les appareils prenant en charge le survol, mais aucun changement pour les appareils tactiles:

.container {
    background-color: red;

    @include hover-supported() {
        background-color: blue;
    }
}
0
Calsal

Pour prendre en charge Firefox (voir https://bugzilla.mozilla.org/show_bug.cgi?id=1035774 ), vous devez potentiellement écrire deux règles deux fois. Notez que, bien que non spécifié dans la question, j'ai ajouté pointer: coarse en supposant que ces règles ont pour but de cibler les écrans mobiles:

/* 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 */

La combinaison de (pointer: coarse) and (hover: none) devrait devenir plus utile pour cibler les appareils mobiles à mesure que les écrans mobiles deviennent plus grands et que nous perdons la corrélation entre les dimensions en pixels et le mobile par rapport au bureau (déjà le cas lorsque vous souhaitez distinguer entre tablette et bureau)

0
EoghanM