Zapytanie o media w celu wykrycia, czy urządzenie jest ekranem dotykowym

123

Jaki jest najbezpieczniejszy sposób za pomocą zapytań o media, aby coś się wydarzyło, gdy nie korzystasz z urządzenia z ekranem dotykowym? Jeśli nie ma sposobu, czy sugerujesz użycie rozwiązania JavaScript, takiego jak !window.Touchlub Modernizr?

JJJollyjim
źródło
2
Szybko do 2018 roku, CSS może teraz natywnie robić to stackoverflow.com/a/50285058/1717735
Buzut

Odpowiedzi:

38

Sugerowałbym użycie modernizr i jego funkcji media query.

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

Jednak używając CSS, istnieją pseudoklasy, takie jak na przykład w Firefoksie. Możesz użyć : -moz-system-metric (z obsługą dotykową) . Ale te funkcje nie są dostępne dla każdej przeglądarki.

W przypadku urządzeń Apple możesz w prosty sposób użyć:

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

Specjalnie dla iPada:

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

Ale te nie działają na Androidzie .

Modernizr daje możliwości wykrywania funkcji, a wykrywanie funkcji to dobry sposób na kodowanie, a nie na kodowanie w oparciu o przeglądarki.

Stylizacja elementów dotykowych

Modernizer dodaje klasy do znacznika HTML właśnie w tym celu. W tym przypadku, toucha no-touchwięc można projektować swoje dotykowe Aspektów poprzedzając swoje selektorów z .touch. np .touch .your-container. Kredyty: Ben Swinburne

Starx
źródło
Czy mam rację myśląc, że żadne klasy psedo nie działają ze wszystkimi nowoczesnymi urządzeniami / przeglądarkami?
JJJollyjim
@ JJ56, Tak, nie każda przeglądarka obsługuje pseudoklasy dotykowe. Ale tam modernizrbędzie idealnie :)
Starx
18
Modernizr.touchTestu wskazuje jedynie, czy przeglądarka obsługuje dotknąć wydarzenia, które niekoniecznie odzwierciedlają urządzenie z ekranem dotykowym. Na przykład telefony Palm Pre / WebOS (dotykowe) nie obsługują zdarzeń dotykowych i dlatego nie przejdą tego testu.
numediaweb
5
Wystarczy dodać do tego, jeśli i tak uwzględniasz modernizatora; Modernizer dodaje klasy do tagu body w tym właśnie celu. W tym przypadku, toucha no-touchwięc można projektować twój dotyk Aspektów poprzedzając swoje selektorów z .touch. Np..touch .your-container
Ben Swinburne
2
Wydaje mi się, że modernizr dodaje klasę dotykową do tagu HTML, a nie body.
Robin Cox
162

Właściwie jest do tego właściwość w wersji roboczej zapytania o media CSS4 .

Funkcja multimediów „wskaźnik” służy do sprawdzania obecności i dokładności urządzenia wskazującego, takiego jak mysz. Jeśli urządzenie ma wiele mechanizmów wejściowych, zaleca się, aby UA zgłaszał charakterystyki najmniej wydajnego urządzenia wskazującego z głównych mechanizmów wejściowych. To zapytanie o media przyjmuje następujące wartości:

„brak”
- mechanizm wprowadzania danych urządzenia nie obejmuje urządzenia wskazującego.

„zgrubny”
- mechanizm wprowadzania urządzenia obejmuje urządzenie wskazujące o ograniczonej dokładności.

„dobrze”
- mechanizm wprowadzania urządzenia obejmuje dokładne urządzenie wskazujące.

Byłoby to używane jako takie:

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

Znalazłem też bilet w projekcie Chromium z tym związany.

Zgodność z przeglądarkami można przetestować w Quirksmode . Oto moje wyniki (22 stycznia 2013):

  • Chrome / Win: działa
  • Chrome / iOS: nie działa
  • Safari / iOS6: nie działa
Znarkus
źródło
3
Jak to może być odpowiedź z największą liczbą punktów, skoro podane rozwiązanie nie działa nawet według plakatu?
erdomester
5
Obsługa przeglądarek nie jest już tak zła: Edge, Chrome, Safari, iOS i Android. Zobacz: caniuse.com/#feat=css-media-interaction
Josa,
3
Dobra odpowiedź. Dodatkowo: developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
aross
U mnie działa;) Dzięki za zbadanie tego!
Verri
53

Wydaje się, że rozwiązania CSS nie są szeroko dostępne od połowy 2013 roku. Zamiast...

  1. Nicholas Zakas wyjaśnia, że Modernizr stosuje no-touchklasę CSS, gdy przeglądarka nie obsługuje dotyku.

  2. Lub wykryj w JavaScript za pomocą prostego fragmentu kodu, co pozwoli Ci zaimplementować własne rozwiązanie podobne do Modernizr:

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

    Następnie możesz napisać swój CSS jako:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
Simon East
źródło
Drugi jest bardzo fajny. U mnie działa urok! Dzięki.
Garavani,
@ bjb568 Dzięki za sugerowaną edycję, która jest nowocześniejszą alternatywą, ale ponieważ działa tylko w IE 10 i nowszych, myślę, że na razie najlepiej jest zachować tę wersję.
Simon East,
Wygląda na to, że ta klasa byłaby w tagu html; co oznaczałoby, że jest domyślnie wyłączone podczas korzystania z CSP.
Leo
36

Typy nośników nie pozwalają na wykrycie funkcji dotykowych w ramach standardu:

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

Dlatego nie ma sposobu, aby zrobić to konsekwentnie za pomocą CSS lub zapytań o media, będziesz musiał uciekać się do JavaScript.

Nie ma potrzeby korzystania z Modernizr, możesz po prostu użyć zwykłego JavaScript:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>
Alex W.
źródło
AFAIK, window.touch&& window.TouchEventdziała tylko na urządzeniach Apple.
Starx,
22
@vsync Modernizr to świetny sposób na umieszczenie wszystkich testów przydatnych dla programistów w utrzymywanej bibliotece, aby nie musieli używać Google za każdym razem, gdy muszą przetestować określoną funkcję, taką jak zdarzenia dotykowe i konieczność znalezienia tej strony. Do Twojej wiadomości jest niestandardowa kompilacja Modernizr, którą możesz dostosować za pomocą żądanych testów. Jest to świetny sposób na testowanie funkcji zawsze w ten sam sposób między projektami, albo używasz składni JS (np .: Modernizr.touch), albo klas CSS (.touch .my-element {}). Myślę, że to zniewaga dla ludzkiej inteligencji, która nie uznaje, że możemy robić rzeczy bez ponownego odkrywania koła za każdym razem.
Alejandro García Iglesias,
11
Cóż, pracowałem nad setkami projektów i nigdy czegoś takiego nie potrzebowałem, w większości przypadków wystarczy bardzo mały zestaw testów, powiedziałbym, że nigdy nie więcej niż 5 (w większości przypadków), więc po prostu znajdź tych 5 i umieszczać je bezpośrednio w kodzie, nie ma potrzeby wchodzenia na stronę Modernizer, tworzenia niestandardowej kompilacji, umieszczania jej na swojej stronie lub cokolwiek innego. Programiści nie powinni być TAK leniwi. Programista stron internetowych powinien zawsze mieć nastawienie „jak mogę uczynić kod lżejszym?” .. IMHO i lata doświadczenia. programiści wydają się obecnie kochać
dołączanie
2
Niektórzy mówią, że jest leniwy. Mówię po co odkrywać koło na nowo? Co się stanie, gdy pojawi się nowe urządzenie / wersja / platforma i Twój przypadek specjalny wymaga zmiany? Czy a) próbujesz samodzielnie opracować specjalny kod do wykrywania przypadków i przenieść się do swojego kodu niestandardowego, ponownie się z nim zapoznajesz, czy b) pobrać nowszą wersję Modernizr i wrzucić ją do niej? Wiem, co bym zrobił. +1 do GarciaWebDev.
Sc0ttyD
@ Sc0ttyD Osobiście preferuję nauczenie się kodowania rzeczy na początku bez zależności od bibliotek, takich jak Modernizr. Któregoś dnia możesz potrzebować być tą osobą, która koduje nowe urządzenie i nie chcesz utknąć, ponieważ nie możesz tego zrobić bez biblioteki. Nie wspominając o tym, że prawdopodobnie jest wiele osób, które po prostu nie mają czasu w swojej pracy, aby uczyć się nowej biblioteki.
Alex W
28

W 2017 roku zapytanie o media CSS z drugiej odpowiedzi nadal nie działa w przeglądarce Firefox. Znalazłem na to rozwiązanie: -moz-touch-enabled


Oto zapytanie o media w różnych przeglądarkach:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}
Sokołowa
źródło
powinno to być wyżej i zatwierdzona odpowiedź. firefox pracuje nad implementacją specyfikacji, więc -moz-touch-enablednie będzie to wkrótce potrzebne
Dogoku
@ user3445853 OP pyta, jak wykryć (poprzez zapytanie o media) urządzenie z ekranem dotykowym. Jeśli reguła „(pointer: none)” będzie prawdziwa, to na pewno urządzenie nie ma ekranu dotykowego. Ale ktoś powinien potwierdzić moją opinię (lub nie) :)
Sokołow
-moz-touch-enabledpodobno nie jest obsługiwany w przeglądarce Firefox 58+. Podobnie jak w przypadku, to rozwiązanie nie obejmuje przeglądarki Firefox 58-63 (ponieważ Firefox 64+ obsługuje zapytanie wskaźnikowe). Źródło: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist
24

W rzeczywistości istnieje zapytanie o media na to:

@media (hover: none) {  }

Oprócz Firefoksa jest dość dobrze obsługiwany . Safari i Chrome są najpopularniejszymi przeglądarkami na urządzeniach mobilnych, więc może wystarczyć do większej adopcji.

Buzut
źródło
2
... a wsparcie pojawi się w kolejnych tygodniach również dla FF.
retrovertigo
5

To zadziała. Jeśli nie, daj mi znać

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

edycja: kursor na żądanie nie jest już obsługiwany

aleksa_95
źródło
3

To rozwiązanie będzie działać, dopóki CSS4 nie będzie globalnie obsługiwany przez wszystkie przeglądarki. Kiedy nadejdzie ten dzień, po prostu użyj CSS4. ale do tego czasu działa to w obecnych przeglądarkach.

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:

stara droga:

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

nowszy sposób:

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

Powyższy kod doda klasę „is-touch” do tagu body, jeśli urządzenie ma ekran dotykowy. Teraz możesz zadzwonić w dowolną lokalizację w swojej aplikacji internetowej, w której miałbyś css dla: hoverbody:not(.is-touch) the_rest_of_my_css:hover

na przykład:

button:hover

staje się:

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

To rozwiązanie pozwala uniknąć używania programu modernizer, ponieważ biblioteka modernizer jest bardzo dużą biblioteką. Jeśli wszystko, co próbujesz zrobić, to wykryć ekrany dotykowe, Najlepiej będzie, gdy wymagany jest rozmiar ostatecznie skompilowanego źródła.

Patrick W. McMahon
źródło
0

dodanie klasycznego ekranu dotykowego do ciała za pomocą JS lub jQuery

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

Udało mi się rozwiązać ten problem za pomocą tego

@media (hover:none), (hover:on-demand) { 
Your class or ID{
attributes
}    
}
Robin Mehdee
źródło
FYI, on-demandzostał usunięty ze specyfikacji oraz z przeglądarkami: github.com/w3c/csswg-drafts/commit/...
retrovertigo