Medienabfrage, um festzustellen, ob das Gerät ein Touchscreen ist

122

Was ist der sicherste Weg, mit Medienabfragen etwas zu bewirken, wenn Sie sich nicht auf einem Touchscreen-Gerät befinden? Wenn dies nicht möglich ist, schlagen Sie die Verwendung einer JavaScript-Lösung wie !window.Touchoder Modernizr vor?

JJJollyjim
quelle
2
Schneller Vorlauf bis 2018, CSS ist jetzt nativ in der Lage, diesen stackoverflow.com/a/50285058/1717735
Buzut

Antworten:

37

Ich würde vorschlagen, modernizr und seine Medienabfragefunktionen zu verwenden.

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

Bei Verwendung von CSS gibt es jedoch Pseudoklassen wie beispielsweise in Firefox. Sie können Folgendes verwenden : -moz-system-metric (touch-enabled) . Diese Funktionen sind jedoch nicht für jeden Browser verfügbar.

Für Apple- Geräte können Sie einfach Folgendes verwenden:

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

Speziell für Ipad:

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

Diese funktionieren jedoch nicht unter Android .

Modernizr bietet Funktionen zur Funktionserkennung, und die Erkennung von Funktionen ist eine gute Möglichkeit zum Codieren, anstatt auf der Basis von Browsern zu codieren.

Styling von Touch-Elementen

Modernizer fügt dem HTML-Tag genau zu diesem Zweck Klassen hinzu. In diesem Fall touchund no-touchso können Sie Ihre Touch bezogene Aspekte Stil durch Ihre Wähler mit .touch prefixing. zB .touch .your-container. Credits: Ben Swinburne

Starx
quelle
Habe ich Recht, wenn ich denke, dass keine Psedo-Klassen mit allen modernen Geräten / Browsern funktionieren?
JJJollyjim
@ JJ56, Ja, nicht jeder Browser unterstützt Touch-Pseudoklassen. Aber hier modernizrwird es perfekt sein :)
Starx
18
Der Modernizr.touchTest zeigt nur an, ob der Browser Berührungsereignisse unterstützt, die nicht unbedingt ein Touchscreen-Gerät widerspiegeln. Beispielsweise unterstützen Palm Pre / WebOS-Telefone (Touch-Telefone) keine Touch-Ereignisse und bestehen diesen Test daher nicht.
Numediaweb
5
Nur um dies zu ergänzen, wenn Sie ohnehin Modernizer einschließen; Modernizer fügt dem Body-Tag genau zu diesem Zweck Klassen hinzu. In diesem Fall touchund no-touchso können Sie Ihre Touch Aspekte Stil können im Zusammenhang mit Ihren Wählern mit prefixing .touch. ZB.touch .your-container
Ben Swinburne
2
Für mich scheint es, dass modernizr dem HTML-Tag eine Touch-Klasse hinzufügt, nicht dem Body-Tag.
Robin Cox
162

Es gibt tatsächlich eine Eigenschaft dafür im CSS4-Medienabfrageentwurf .

Die Medienfunktion "Zeiger" wird verwendet, um das Vorhandensein und die Genauigkeit eines Zeigegeräts wie einer Maus abzufragen. Wenn ein Gerät über mehrere Eingabemechanismen verfügt, wird empfohlen, dass die UA die Eigenschaften des am wenigsten leistungsfähigen Zeigegeräts der primären Eingabemechanismen meldet. Diese Medienabfrage nimmt die folgenden Werte an:

'none'
- Der Eingabemechanismus des Geräts enthält kein Zeigegerät.

'grob'
- Der Eingabemechanismus des Geräts enthält ein Zeigegerät mit begrenzter Genauigkeit.

'fein'
- Der Eingabemechanismus des Geräts enthält ein genaues Zeigegerät.

Dies würde als solches verwendet werden:

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

Ich habe auch ein Ticket im Chromium-Projekt gefunden, das damit zusammenhängt.

Die Browserkompatibilität kann im Quirksmode getestet werden . Dies sind meine Ergebnisse (22. Januar 2013):

  • Chrome / Win: Funktioniert
  • Chrome / iOS: Funktioniert nicht
  • Safari / iOS6: Funktioniert nicht
Znarkus
quelle
3
Wie kann dies die Antwort mit den meisten Punkten sein, wenn die bereitgestellte Lösung nicht einmal laut Poster funktioniert?
Erdomester
5
Die Browserunterstützung dafür ist nicht mehr so ​​schlecht: Edge, Chrome, Safari, iOS und Android. Siehe: caniuse.com/#feat=css-media-interaction
Josa
3
Gute Antwort. Zusätzlich: developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
über den
Funktioniert für mich;) Danke für die Recherche!
Verri
51

Die CSS-Lösungen scheinen ab Mitte 2013 nicht weit verbreitet zu sein. Stattdessen...

  1. Nicholas Zakas erklärt, dass Modernizr eine no-touchCSS-Klasse anwendet, wenn der Browser Touch nicht unterstützt.

  2. Oder erkennen Sie in JavaScript mit einem einfachen Code, mit dem Sie Ihre eigene Modernizr-ähnliche Lösung implementieren können:

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

    Dann können Sie Ihr CSS schreiben als:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
Simon East
quelle
Der zweite ist sehr schön. Wirkt ein Zauber für mich! Vielen Dank.
Garavani
@ bjb568 Vielen Dank für die vorgeschlagene Bearbeitung, die eine modernere Alternative darstellt. Da sie jedoch nur in IE 10 und höher funktioniert, ist es meiner Meinung nach am besten, diese Version vorerst beizubehalten.
Simon East
Klingt so, als würde sich diese Klasse auf dem HTML-Tag befinden. Dies würde dann bedeuten, dass es bei Verwendung von CSP standardmäßig deaktiviert ist.
Leo
35

Bei Medientypen können Sie Touch-Funktionen nicht als Teil des Standards erkennen:

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

Es gibt also keine Möglichkeit, dies konsistent über CSS oder Medienabfragen zu tun. Sie müssen auf JavaScript zurückgreifen.

Sie müssen Modernizr nicht verwenden, sondern können einfach nur JavaScript verwenden:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>
Alex W.
quelle
AFAIK window.touch&& window.TouchEventfunktioniert nur für Apple-Geräte.
Starx
22
@vsync Modernizr ist eine großartige Möglichkeit, alle für Entwickler nützlichen Tests in einer verwalteten Bibliothek abzulegen, damit sie nicht jedes Mal googeln müssen, wenn sie eine bestimmte Funktion wie Berührungsereignisse testen und diese Seite finden müssen. Zu Ihrer Information gibt es einen benutzerdefinierten Modernizr-Build, den Sie mit den gewünschten Tests anpassen können. Es ist eine großartige Möglichkeit, Funktionen zwischen Projekten immer auf die gleiche Weise zu testen. Entweder verwenden Sie die JS-Syntax (dh Modernizr.touch) oder die CSS-Klassen (.touch .my-element {}). Ich denke, es ist eine Beleidigung für die menschliche Intelligenz, nicht zu erkennen, dass wir Dinge tun können, ohne das Rad jedes Mal neu zu erfinden.
Alejandro García Iglesias
11
Nun, ich habe an Hunderten von Projekten gearbeitet und ich habe so etwas nie gebraucht. In den meisten Fällen brauchen Sie nur eine sehr kleine Anzahl von Tests, nie mehr als 5, würde ich sagen (in den meisten Fällen) Diese 5 und fügen Sie sie direkt in Ihren Code ein. Sie müssen nicht unbedingt zur Modernizer-Website gehen, einen benutzerdefinierten Build erstellen, ihn in Ihre Seite aufnehmen oder was auch immer. Entwickler sollten nicht so faul sein. Ein Webentwickler sollte immer die Einstellung haben, "wie kann ich den Code leichter machen?". IMHO und jahrelange Erfahrung. Entwickler scheinen heutzutage zu lieben, Tonnen von Skripten
einzuschließen
2
Einige sagen faul. Ich sage, warum das Rad neu erfinden? Was ist, wenn ein neues Gerät / eine neue Version / Plattform erscheint und Ihr Sonderfall geändert werden muss? Versuchen Sie a), den Code zur Erkennung von Sonderfällen selbst zu erarbeiten und auf Ihren benutzerdefinierten Code zurück zu portieren, um sich damit erneut vertraut zu machen, oder b) eine neuere Version von Modernizr herunterzuladen und dort abzulegen? Ich weiß was ich tun würde. +1 an GarciaWebDev.
Sc0ttyD
@ Sc0ttyD Meine persönliche Präferenz ist es, zunächst zu lernen, Dinge zu codieren, ohne von Bibliotheken wie Modernizr abhängig zu sein. Eines Tages müssen Sie möglicherweise die Person sein, die für das neue Gerät codiert, und Sie möchten nicht stecken bleiben, weil Sie dies nicht ohne eine Bibliothek tun können. Ganz zu schweigen davon, dass es wahrscheinlich viele Leute gibt, die einfach nicht die Zeit haben, eine neue Bibliothek zu lernen.
Alex W
28

Im Jahr 2017 funktioniert die CSS-Medienabfrage aus der zweiten Antwort in Firefox immer noch nicht. Ich habe eine Lösung dafür gefunden: -moz-touch-enabled


Hier ist also eine browserübergreifende Medienabfrage:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}
Sokołow
quelle
Dies sollte höher und die genehmigte Antwort sein. Firefox arbeitet an der Implementierung der Spezifikation, -moz-touch-enabledwird also nicht bald benötigt
Dogoku
kann nach dem 11. Dezember '18 aktualisiert werden wiki.mozilla.org/Release_Management/Calendar developer.mozilla.org/en-US/docs/Web/CSS/@media/…
retrovertigo
@ user3445853 OP fragt, wie das Gerät (über eine Medienabfrage) mit einem Touchscreen erkannt werden soll. Wenn die Regel "(Zeiger: keine)" wahr ist, verfügt das Gerät mit Sicherheit nicht über einen Touchscreen. Aber jemand sollte meine Meinung bestätigen (oder nein) :)
Sokołow
-moz-touch-enabledwird in Firefox 58+ angeblich nicht unterstützt. Wie in deckt diese Lösung Firefox 58-63 nicht ab (da Firefox 64+ die Zeigerabfrage unterstützt). Quelle: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist
24

Dafür gibt es tatsächlich eine Medienabfrage:

@media (hover: none) {  }

Abgesehen von Firefox wird es ziemlich gut unterstützt . Safari und Chrome sind die am häufigsten verwendeten Browser auf Mobilgeräten und können bis zu einer größeren Akzeptanz ausreichen.

Buzut
quelle
2
... und Unterstützung für FF in den folgenden Wochen.
Retrovertigo
5

Das wird funktionieren. Wenn es mich nicht wissen lässt

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

edit: hover on-demand wird nicht mehr unterstützt

aleksa_95
quelle
3

Diese Lösung funktioniert so lange, bis CSS4 von allen Browsern global unterstützt wird. Wenn dieser Tag kommt, verwenden Sie einfach CSS4. Bis dahin funktioniert dies jedoch für aktuelle Browser.

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:

Alter Weg:

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

neuerer Weg:

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

Mit dem obigen Code wird die Klasse "is-touch" zum Body-Tag hinzugefügt, wenn das Gerät über einen Touchscreen verfügt. Jetzt können Sie an jedem Ort in Ihrer Webanwendung, für den Sie CSS haben würden, den Hover aufrufenbody:not(.is-touch) the_rest_of_my_css:hover

beispielsweise:

button:hover

wird:

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

Diese Lösung vermeidet die Verwendung von Modernizer, da die Modernizer-Bibliothek eine sehr große Bibliothek ist. Wenn Sie nur versuchen, Touchscreens zu erkennen, ist dies am besten, wenn die Größe der endgültig kompilierten Quelle erforderlich ist.

Patrick W. McMahon
quelle
0

Hinzufügen eines Klassen-Touchscreens zum Körper mit JS oder jQuery

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

Ich konnte dieses Problem damit beheben

@media (hover:none), (hover:on-demand) { 
Your class or ID{
attributes
}    
}
Robin Mehdee
quelle
Zu Ihrer Information, on-demandwurde aus der Spezifikation und aus den Browsern entfernt: github.com/w3c/csswg-drafts/commit/…
retrovertigo