Media query per rilevare se il dispositivo è touchscreen


122

Qual è il modo più sicuro, utilizzando le media query, per far accadere qualcosa quando non si è su un dispositivo touchscreen? Se non è possibile, suggerisci di utilizzare una soluzione JavaScript come !window.Toucho Modernizr?


2
Fast forward al 2018, CSS è ora in modo nativo in grado di fare questo stackoverflow.com/a/50285058/1717735
Buzut

Risposte:


37

Suggerirei di utilizzare modernizr e di utilizzare le sue funzionalità di media query.

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

Tuttavia, utilizzando CSS, ci sono pseudo classi come, ad esempio, in Firefox. Puoi usare : -moz-system-metric (abilitato al tocco) . Ma queste funzionalità non sono disponibili per tutti i browser.

Per i dispositivi Apple , puoi usare semplicemente:

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

Soprattutto per Ipad:

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

Ma questi non funzionano su Android .

Modernizr offre capacità di rilevamento delle funzionalità e il rilevamento delle funzionalità è un buon modo per codificare, piuttosto che codificare sulla base dei browser.

Styling Touch Elements

Modernizer aggiunge classi al tag HTML per questo scopo esatto. In questo caso, touche no-touchin modo da poter stile tuoi aspetti legati tocco anteponendo i vostri selettori con .touch. es .touch .your-container. Crediti: Ben Swinburne


Ho ragione nel pensare che nessuna classe psedo funziona con tutti i dispositivi / browser moderni?
JJJollyjim

@ JJ56, Sì, non tutti i browser supportano le pseudo classi touch. Ma è lì modernizrche sarà perfetto :)
Starx

18
Il Modernizr.touchtest indica solo se il browser supporta eventi touch, che non riflettono necessariamente un dispositivo touchscreen. Ad esempio, i telefoni Palm Pre / WebOS (touch) non supportano eventi di tocco e quindi non superano questo test.
numediaweb

5
Solo per aggiungere a questo, se includi comunque il modernizzatore; Modernizer aggiunge classi al tag body per questo scopo esatto. In questo caso, touche no-touchin modo da poter stile il tuo tocco legato aspetti anteponendo i vostri selettori con .touch. Ad esempio.touch .your-container
Ben Swinburne

2
Per me sembra che modernizr aggiunga la classe touch al tag html, non al tag body.
Robin Cox

162

In realtà c'è una proprietà per questo nella bozza di media query CSS4 .

La funzione multimediale "puntatore" viene utilizzata per interrogare la presenza e l'accuratezza di un dispositivo di puntamento come un mouse. Se un dispositivo dispone di più meccanismi di input, si consiglia che l'UA riporti le caratteristiche del dispositivo di puntamento meno capace dei meccanismi di input primari. Questa media query assume i seguenti valori:

'none'
- Il meccanismo di input del dispositivo non include un dispositivo di puntamento.

"grossolano"
- Il meccanismo di input del dispositivo include un dispositivo di puntamento di precisione limitata.

'fine'
- Il meccanismo di input del dispositivo include un dispositivo di puntamento accurato.

Questo sarebbe usato come tale:

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

Ho anche trovato un biglietto nel progetto Chromium relativo a questo.

La compatibilità del browser può essere testata su Quirksmode . Questi sono i miei risultati (22 gennaio 2013):

  • Chrome / Win: funziona
  • Chrome / iOS: non funziona
  • Safari / iOS6: non funziona

3
Come può essere questa la risposta con il maggior numero di punti quando la soluzione fornita non funziona nemmeno secondo il poster?
erdomester

5
Il supporto del browser per questo non è più così male: Edge, Chrome, Safari, iOS e Android. Vedi: caniuse.com/#feat=css-media-interaction
Josa


Funziona per me;) Grazie per la ricerca questo!
Verri

53

Le soluzioni CSS non sembrano essere ampiamente disponibili a partire dalla metà del 2013. Anziché...

  1. Nicholas Zakas spiega che Modernizr applica una no-touchclasse CSS quando il browser non supporta il tocco.

  2. Oppure rileva in JavaScript con un semplice pezzo di codice, permettendoti di implementare la tua soluzione simile a Modernizr:

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

    Quindi puoi scrivere il tuo CSS come:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }

Il secondo è molto carino. Funziona un fascino per me! Grazie.
Garavani

@ bjb568 Grazie per la modifica suggerita, che è un'alternativa più moderna, ma poiché funziona solo in IE 10 e versioni successive, penso che sia meglio mantenere questa versione per il momento.
Simon East

Sembra che quella classe sia sul tag html; il che significherebbe che è disabilitato per impostazione predefinita quando si utilizza CSP.
Leone

36

I tipi di supporto non consentono di rilevare le funzionalità di tocco come parte dello standard:

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

Quindi, non c'è modo di farlo in modo coerente tramite CSS o media query, dovrai ricorrere a JavaScript.

Non è necessario utilizzare Modernizr, puoi semplicemente usare JavaScript semplice:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>

AFAIK, window.touch&& window.TouchEventfunziona solo per i dispositivi Apple.
Starx

22
@vsync Modernizr è un ottimo modo per mettere tutti i test utili per gli sviluppatori in una libreria mantenuta, in modo che non debbano collegarsi a Google ogni volta che devono testare una funzionalità specifica, come eventi di tocco e dover trovare questa pagina. Cordiali saluti, c'è una build Modernizr personalizzata che puoi personalizzare con i test che desideri. È un ottimo modo per testare le funzionalità sempre allo stesso modo tra i progetti, sia che utilizzi la sintassi JS (ad esempio: Modernizr.touch) o le classi CSS (.touch .my-element {}). Penso che sia un insulto all'intelligenza umana non riconoscere che possiamo fare le cose senza reinventare ogni volta la ruota.
Alejandro García Iglesias

11
Bene, ho lavorato a centinaia di progetti e non ho mai avuto bisogno di una cosa del genere, nella maggior parte dei casi tutto ciò di cui hai bisogno è una serie molto piccola di test, mai più di 5 direi (nella maggior parte dei casi), quindi trova quei 5 e inserirli direttamente nel codice, non è necessario andare effettivamente al sito Web di Modernizer, creare una build personalizzata, includerla nella pagina o altro. Gli sviluppatori non dovrebbero essere così pigri. Uno sviluppatore web dovrebbe sempre avere la mentalità di "come posso rendere il codice più leggero?" .. IMHO e anni di esperienza. agli sviluppatori oggigiorno sembra piacere includere tonnellate di script: /
vsync

2
Alcuni dicono pigro. Dico perché reinventare la ruota? Che cosa succede quando viene visualizzato un nuovo dispositivo / versione / piattaforma e il tuo caso speciale deve essere modificato? A) Tenti di elaborare tu stesso il codice di rilevamento dei casi speciali e fai il backport al tuo codice personalizzato, riprendendoti con esso nel processo, oppure b) scarichi una versione più recente di Modernizr e rilasciala? So cosa farei. +1 a GarciaWebDev.
Sc0ttyD

@ Sc0ttyD La mia preferenza personale è imparare a programmare le cose inizialmente senza dipendere da librerie come Modernizr. Un giorno potresti dover essere quella persona che codifica per il nuovo dispositivo e non vuoi rimanere bloccato perché non puoi farlo senza una libreria. Per non parlare del fatto che probabilmente ci sono molte persone che semplicemente non hanno il tempo al loro lavoro per imparare una nuova biblioteca.
Alex W

28

Nel 2017, la query multimediale CSS dalla seconda risposta non funziona ancora su Firefox. Ho trovato una soluzione per questo: -moz-touch-enabled


Quindi, ecco la media query cross-browser:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}

questo dovrebbe essere più in alto e la risposta approvata. Firefox sta lavorando all'implementazione delle specifiche, quindi -moz-touch-enablednon sarà richiesto a breve
Dogoku


@ user3445853 OP chiede come rilevare (tramite media query) il dispositivo con un touchscreen. Se la regola "(puntatore: nessuno)" sarà vera, il dispositivo non ha sicuramente un touchscreen. Ma qualcuno dovrebbe confermare la mia opinione (o no) :)
Sokołow

-moz-touch-enabledpresumibilmente non è supportato in Firefox 58+. Come in, questa soluzione non copre Firefox 58-63 (poiché Firefox 64+ supporta la query del puntatore). Fonte: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist

24

In realtà c'è una media query per questo:

@media (hover: none) {  }

Oltre a Firefox, è abbastanza ben supportato . Essendo Safari e Chrome i browser più comuni sui dispositivi mobili, potrebbe bastare fino a una maggiore adozione.


2
... e il supporto in arrivo nelle prossime settimane anche per FF.
retrovertigo

5

Questo funzionerà. Se non me lo fa sapere

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

modifica: il passaggio del mouse su richiesta non è più supportato


3

Questa soluzione funzionerà fino a quando CSS4 non sarà supportato globalmente da tutti i browser. Quando arriverà quel giorno, usa i CSS4. ma fino ad allora, questo funziona per i browser attuali.

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

onload:

vecchio modo:

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

modo più nuovo:

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

Il codice sopra aggiungerà la classe "is-touch" al tag del corpo se il dispositivo ha un touch screen. Ora qualsiasi posizione nella tua applicazione web dove avresti css per: hover puoi chiamarebody:not(.is-touch) the_rest_of_my_css:hover

per esempio:

button:hover

diventa:

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

Questa soluzione evita l'uso di modernizer poiché la libreria di modernizer è una libreria molto grande. Se tutto ciò che stai cercando di fare è rilevare i touch screen, sarà la cosa migliore quando la dimensione della sorgente compilata finale è un requisito.


0

l'aggiunta di un touchscreen di classe al corpo utilizzando JS o jQuery

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.