Requête multimédia pour détecter si l'appareil est un écran tactile

122

Quel est le moyen le plus sûr, à l'aide de requêtes multimédias, de faire en sorte que quelque chose se produise lorsque vous n'êtes pas sur un appareil à écran tactile? S'il n'y a aucun moyen, suggérez-vous d'utiliser une solution JavaScript telle que !window.Touchou Modernizr?

JJJollyjim
la source
2
Avance rapide jusqu'en 2018, CSS est maintenant capable de faire ce stackoverflow.com/a/50285058/1717735
Buzut

Réponses:

37

Je suggérerais d'utiliser modernizr et d'utiliser ses fonctionnalités de requête multimédia.

if (Modernizr.touch){
   // bind to touchstart, touchmove, etc and watch `event.streamId`
} else {
   // bind to normal click, mousemove, etc
}

Cependant, en utilisant CSS, il existe des pseudo-classes comme, par exemple, dans Firefox. Vous pouvez utiliser : -moz-system-metric (tactile) . Mais ces fonctionnalités ne sont pas disponibles pour tous les navigateurs.

Pour les appareils Apple , vous pouvez utiliser simplement:

if(window.TouchEvent) {
   //.....
}

Surtout pour Ipad:

if(window.Touch) {
    //....
}

Mais, ceux - ci ne fonctionnent pas sur Android .

Modernizr offre des capacités de détection de fonctionnalités, et la détection des fonctionnalités est un bon moyen de coder, plutôt que de coder sur la base des navigateurs.

Styling des éléments tactiles

Modernizer ajoute des classes à la balise HTML dans ce but précis. Dans ce cas, touchet no-touchainsi vous pouvez styliser vos aspects liés au toucher en préfixant vos sélecteurs avec .touch. par exemple .touch .your-container. Crédits: Ben Swinburne

Starx
la source
Ai-je raison de penser qu'aucune classe psedo ne fonctionne avec tous les appareils / navigateurs modernes?
JJJollyjim
@ JJ56, Oui, tous les navigateurs ne prennent pas en charge les pseudo-classes tactiles. Mais c'est là que modernizrsera parfait :)
Starx
18
Le Modernizr.touchtest indique uniquement si le navigateur prend en charge les événements tactiles, ce qui ne reflète pas nécessairement un appareil à écran tactile. Par exemple, les téléphones Palm Pre / WebOS (tactiles) ne prennent pas en charge les événements tactiles et échouent donc à ce test.
numediaweb
5
Juste pour ajouter à cela, si vous incluez de toute façon un moderniseur; Modernizer ajoute des classes à la balise body dans ce but précis. Dans ce cas, touchet no-touchainsi vous pouvez styliser vos aspects liés au toucher en préfixant vos sélecteurs avec .touch. Par exemple.touch .your-container
Ben Swinburne
2
Pour moi, il semble que modernizr ajoute une classe tactile à la balise html, pas à la balise body.
Robin Cox
162

Il existe en fait une propriété pour cela dans le brouillon de requête multimédia CSS4 .

La fonction multimédia "pointeur" est utilisée pour interroger la présence et la précision d'un périphérique de pointage tel qu'une souris. Si un périphérique possède plusieurs mécanismes d'entrée, il est recommandé que l'UA indique les caractéristiques du périphérique de pointage le moins capable des mécanismes d'entrée principaux. Cette requête multimédia prend les valeurs suivantes:

'aucun'
- Le mécanisme d'entrée du périphérique n'inclut pas de périphérique de pointage.

«grossier»
- Le mécanisme d'entrée de l'appareil comprend un dispositif de pointage d'une précision limitée.

'fine'
- Le mécanisme d'entrée de l'appareil comprend un dispositif de pointage précis.

Cela serait utilisé comme tel:

/* Make radio buttons and check boxes larger if we have an inaccurate pointing device */
@media (pointer:coarse) {
    input[type="checkbox"], input[type="radio"] {
        min-width:30px;
        min-height:40px;
        background:transparent;
    }
}

J'ai également trouvé un ticket dans le projet Chromium lié à cela.

La compatibilité du navigateur peut être testée à Quirksmode . Voici mes résultats (22 janvier 2013):

  • Chrome / Win: fonctionne
  • Chrome / iOS: ne fonctionne pas
  • Safari / iOS6: ne fonctionne pas
Znarkus
la source
3
Comment cela peut-il être la réponse avec le plus de points lorsque la solution fournie ne fonctionne pas même selon l'affiche?
erdomester
5
Le support du navigateur pour cela n'est plus aussi mauvais: Edge, Chrome, Safari, iOS et Android. Voir: caniuse.com/#feat=css-media-interaction
Josa
3
Bonne réponse. De plus: developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
partir du
Fonctionne pour moi;) Merci pour cette recherche!
Verri
53

Les solutions CSS ne semblent pas être largement disponibles à la mi-2013. Au lieu...

  1. Nicholas Zakas explique que Modernizr applique une no-touchclasse CSS lorsque le navigateur ne prend pas en charge le toucher.

  2. Ou détectez en JavaScript avec un simple morceau de code, vous permettant de mettre en œuvre votre propre solution de type Modernizr:

    <script>
        document.documentElement.className += 
        (("ontouchstart" in document.documentElement) ? ' touch' : ' no-touch');
    </script>

    Ensuite, vous pouvez écrire votre CSS comme suit:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
Simon Est
la source
Le second est très sympa. Fonctionne un charme pour moi! Merci.
Garavani
@ bjb568 Merci pour la modification suggérée, qui est une alternative plus moderne, mais comme elle ne fonctionne que dans IE 10 et au-dessus, je pense qu'il est préférable de conserver cette version pour le moment.
Simon East
On dirait que cette classe serait sur la balise html; ce qui signifierait alors qu'il est désactivé par défaut lors de l'utilisation de CSP.
Leo
36

Les types de support ne vous permettent pas de détecter les capacités tactiles dans le cadre de la norme:

http://www.w3.org/TR/css3-mediaqueries/

Donc, il n'y a aucun moyen de le faire de manière cohérente via CSS ou des requêtes multimédias, vous devrez recourir à JavaScript.

Pas besoin d'utiliser Modernizr, vous pouvez simplement utiliser du JavaScript simple:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>
Alex W
la source
AFAIK et window.touch&& window.TouchEventne fonctionnent que pour les appareils Apple.
Starx
22
@vsync Modernizr est un excellent moyen de mettre tous les tests utiles aux développeurs dans une bibliothèque maintenue, pour qu'ils n'aient pas à Google à chaque fois qu'ils ont besoin de tester une fonctionnalité spécifique, comme les événements tactiles et d'avoir à trouver cette page. Pour info, il existe une version personnalisée de Modernizr que vous pouvez personnaliser avec les tests que vous souhaitez. C'est un excellent moyen de tester les fonctionnalités toujours de la même manière entre les projets, soit vous utilisez la syntaxe JS (ie: Modernizr.touch), soit les classes CSS (.touch .my-element {}). Je pense que c'est une insulte à l'intelligence humaine de ne pas reconnaître que nous pouvons faire des choses sans réinventer la roue à chaque fois.
Alejandro García Iglesias
11
Eh bien, j'ai travaillé sur des centaines de projets et je n'ai jamais eu besoin d'une telle chose, dans la plupart des cas, tout ce dont vous avez besoin est un très petit ensemble de tests, jamais plus de 5 je dirais (dans la plupart des cas), alors trouvez ces 5 et mettez-les directement dans votre code, pas besoin d'aller sur le site Web de Modernizer, de créer une version personnalisée, de l'inclure dans votre page, ou autre. Les développeurs ne devraient pas être SI paresseux. Un développeur Web doit toujours avoir la mentalité de "comment puis-je rendre le code plus léger?" .. IMHO et des années d'expérience. les développeurs de nos jours semblent aimer inclure des tonnes de scripts: /
vsync
2
Certains disent paresseux. Je dis pourquoi réinventer la roue? Qu'en est-il lorsqu'un nouvel appareil / version / plate-forme apparaît et que votre cas particulier doit changer? Avez-vous a) Tentez-vous d'élaborer vous-même un code de détection de cas spécial et rétroportez-vous vers votre code personnalisé, en vous familiarisant à nouveau avec lui dans le processus, ou b) téléchargez-vous une version plus récente de Modernizr et déposez-la? Je sais ce que je ferais. +1 à GarciaWebDev.
Sc0ttyD
@ Sc0ttyD Ma préférence personnelle est d'apprendre à coder des choses au départ sans dépendre de bibliothèques telles que Modernizr. Un jour, vous devrez peut-être être cette personne codant pour le nouvel appareil et vous ne voulez pas être bloqué parce que vous ne pouvez pas le faire sans bibliothèque. Sans oublier, il y a probablement beaucoup de gens qui n'ont tout simplement pas le temps à leur travail d'apprendre une nouvelle bibliothèque.
Alex W
28

En 2017, la requête multimédia CSS de la deuxième réponse ne fonctionne toujours pas sur Firefox. J'ai trouvé une solution pour ça: -moz-touch-enabled


Alors, voici la requête multimédia multi-navigateurs:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}
Sokołow
la source
cela devrait être plus haut et la réponse approuvée. firefox travaille sur la mise en œuvre de la spécification, donc -moz-touch-enabledne sera pas nécessaire bientôt
Dogoku
peut être mis à jour après le 11 décembre. '18 wiki.mozilla.org/Release_Management/Calendar developer.mozilla.org/en-US/docs/Web/CSS/@media/…
retrovertigo
@ user3445853 OP demande comment détecter (via une requête multimédia) l'appareil avec un écran tactile. Si la règle "(pointeur: aucun)" est vraie, alors l'appareil n'a pas d'écran tactile à coup sûr. Mais quelqu'un devrait confirmer mon opinion (ou non) :)
Sokołow
-moz-touch-enabledn'est pas pris en charge dans Firefox 58+. Comme dans, cette solution ne couvre pas Firefox 58-63 (puisque Firefox 64+ prend en charge la requête pointeur). Source: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist
24

Il y a en fait une requête média pour cela:

@media (hover: none) {  }

En dehors de Firefox, il est assez bien pris en charge . Safari et Chrome étant les navigateurs les plus courants sur les appareils mobiles, cela pourrait suffire jusqu'à une plus grande adoption.

Buzut
la source
2
... et du soutien à venir dans les semaines suivantes pour FF également.
retrovertigo
5

Cela fonctionnera. Si ça ne me fait pas savoir

@media (hover: none) and (pointer: coarse) {
    /* Touch screen device style goes here */
}

edit: le survol à la demande n'est plus pris en charge

aleksa_95
la source
3

Cette solution fonctionnera jusqu'à ce que CSS4 soit globalement pris en charge par tous les navigateurs. Quand ce jour viendra, utilisez simplement CSS4. mais jusque-là, cela fonctionne pour les navigateurs actuels.

browser-util.js

export const isMobile = {
  android: () => navigator.userAgent.match(/Android/i),
  blackberry: () => navigator.userAgent.match(/BlackBerry/i),
  ios: () => navigator.userAgent.match(/iPhone|iPad|iPod/i),
  opera: () => navigator.userAgent.match(/Opera Mini/i),
  windows: () => navigator.userAgent.match(/IEMobile/i),
  any: () => (isMobile.android() || isMobile.blackberry() || 
  isMobile.ios() || isMobile.opera() || isMobile.windows())
};

en charge:

ancienne façon:

isMobile.any() ? document.getElementsByTagName("body")[0].className += 'is-touch' : null;

nouvelle façon:

isMobile.any() ? document.body.classList.add('is-touch') : null;

Le code ci-dessus ajoutera la classe "is-touch" à l'étiquette corporelle si l'appareil dispose d'un écran tactile. Maintenant, n'importe quel emplacement dans votre application Web où vous auriez un css pour: survolez vous pouvez appelerbody:not(.is-touch) the_rest_of_my_css:hover

par exemple:

button:hover

devient:

body:not(.is-touch) button:hover

Cette solution évite d'utiliser modernizer car la lib modernizer est une très grande bibliothèque. Si tout ce que vous essayez de faire est de détecter les écrans tactiles, ce sera mieux lorsque la taille de la source compilée finale est une exigence.

Patrick W. McMahon
la source
0

ajouter un écran tactile de classe au corps en utilisant JS ou jQuery

  //allowing mobile only css
    var isMobile = ('ontouchstart' in document.documentElement && navigator.userAgent.match(/Mobi/));
    if(isMobile){
        jQuery("body").attr("class",'touchscreen');
    }
Matoeil
la source
0

J'ai pu résoudre ce problème en utilisant ceci

@media (hover:none), (hover:on-demand) { 
Your class or ID{
attributes
}    
}
Robin Mehdee
la source
FYI, on-demanda été supprimé des spécifications et des navigateurs: github.com/w3c/csswg-drafts/commit/…
retrovertigo