Kueri media untuk mendeteksi apakah perangkat adalah layar sentuh

122

Apa cara teraman, menggunakan kueri media, untuk membuat sesuatu terjadi saat tidak menggunakan perangkat layar sentuh? Jika tidak ada cara, apakah Anda menyarankan menggunakan solusi JavaScript seperti !window.Touchatau Modernizr?

JJJollyjim
sumber
2
Maju cepat ke 2018, CSS sekarang secara native dapat melakukan stackoverflow.com/a/50285058/1717735
Buzut

Jawaban:

37

Saya menyarankan menggunakan modernizr dan menggunakan fitur kueri medianya.

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

Namun menggunakan CSS, ada pseudo class seperti misalnya di Firefox. Anda dapat menggunakan : -moz-system-metric (kompatibel dengan sentuhan) . Namun fitur ini tidak tersedia untuk setiap browser.

Untuk perangkat Apple , Anda dapat menggunakan:

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

Khusus untuk Ipad:

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

Tapi, ini tidak berfungsi di Android .

Modernizr memberikan kemampuan deteksi fitur, dan mendeteksi fitur adalah cara yang baik untuk membuat kode, daripada membuat kode berdasarkan browser.

Styling Elemen Sentuh

Modernizer menambahkan kelas ke tag HTML untuk tujuan yang tepat ini. Dalam hal ini, touchdan no-touchsehingga Anda dapat gaya aspek yang berhubungan sentuhan Anda dengan awalan selektor Anda dengan .touch. mis .touch .your-container. Penghargaan: Ben Swinburne

Starx
sumber
Apakah saya benar dalam berpikir bahwa tidak ada kelas psedo yang berfungsi dengan semua perangkat / browser modern?
JJJollyjim
@ JJ56, Ya, tidak semua browser mendukung kelas pseudo sentuh. Tapi di situlah modernizrakan menjadi sempurna :)
Starx
18
The Modernizr.touchtes hanya menunjukkan jika dukungan browser yang menyentuh peristiwa, yang tidak selalu mencerminkan perangkat touchscreen. Misalnya, ponsel Palm Pre / WebOS (sentuh) tidak mendukung aktivitas sentuh sehingga gagal dalam pengujian ini.
numediaweb
5
Hanya untuk menambahkan ini, jika Anda tetap termasuk modernizer; Modernizer menambahkan kelas ke tag tubuh untuk tujuan yang tepat ini. Dalam hal ini, touchdan no-touchsehingga Anda dapat gaya sentuhan Anda terkait aspek dengan awalan selektor Anda dengan .touch. Misalnya.touch .your-container
Ben Swinburne
2
Bagi saya tampaknya modernizr menambahkan kelas sentuh ke tag html, bukan tag body.
Robin Cox
162

Sebenarnya ada properti untuk ini di draf kueri media CSS4 .

Fitur media 'pointer' digunakan untuk menanyakan tentang keberadaan dan akurasi perangkat penunjuk seperti mouse. Jika perangkat memiliki beberapa mekanisme masukan, disarankan agar UA melaporkan karakteristik perangkat penunjuk yang paling tidak mampu dari mekanisme masukan utama. Kueri media ini mengambil nilai-nilai berikut:

'none'
- Mekanisme input perangkat tidak termasuk perangkat penunjuk.

'kasar'
- Mekanisme input perangkat mencakup perangkat penunjuk dengan akurasi terbatas.

'fine'
- Mekanisme input perangkat mencakup perangkat penunjuk yang akurat.

Ini akan digunakan seperti itu:

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

Saya juga menemukan tiket di proyek Chromium yang terkait dengan ini.

Kompatibilitas browser dapat diuji di Quirksmode . Ini adalah hasil saya (22 jan 2013):

  • Chrome / Win: Bekerja
  • Chrome / iOS: Tidak berfungsi
  • Safari / iOS6: Tidak berfungsi
Znarkus
sumber
3
Bagaimana ini bisa menjadi jawaban dengan poin terbanyak ketika solusi yang diberikan tidak berfungsi bahkan sesuai dengan poster?
erdomester
5
Dukungan browser untuk ini tidak seburuk lagi: Edge, Chrome, Safari, iOS dan Android. Lihat: caniuse.com/#feat=css-media-interaction
Josa
3
Jawaban yang bagus. Selain itu: developer.mozilla.org/en-US/docs/Web/CSS/@media/hover
aross
Bekerja untuk saya;) Terima kasih untuk penelitian ini!
Verri
53

Solusi CSS tampaknya tidak tersedia secara luas mulai pertengahan 2013. Sebagai gantinya...

  1. Nicholas Zakas menjelaskan bahwa Modernizr menerapkan no-touchkelas CSS saat browser tidak mendukung sentuhan.

  2. Atau deteksi dalam JavaScript dengan potongan kode sederhana, memungkinkan Anda menerapkan solusi mirip Modernizr Anda sendiri:

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

    Kemudian Anda dapat menulis CSS Anda sebagai:

    .no-touch .myClass {
        ...
    }
    .touch .myClass {
        ...
    }
Simon Timur
sumber
Yang kedua sangat bagus. Sangat mempesona bagi saya! Terima kasih.
Garavani
@ bjb568 Terima kasih atas pengeditan yang disarankan, yang merupakan alternatif yang lebih modern, tetapi karena ini hanya berfungsi di IE 10 dan yang lebih baru, saya rasa yang terbaik adalah menyimpan versi ini untuk saat ini.
Simon East
Kedengarannya seperti kelas itu akan ada di tag html; yang berarti itu dinonaktifkan secara default saat menggunakan CSP.
Leo
36

Jenis media tidak memungkinkan Anda mendeteksi kapabilitas sentuh sebagai bagian dari standar:

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

Jadi, tidak ada cara untuk melakukannya secara konsisten melalui CSS atau kueri media, Anda harus menggunakan JavaScript.

Tidak perlu menggunakan Modernizr, Anda cukup menggunakan JavaScript biasa:

<script type="text/javascript">
    var is_touch_device = 'ontouchstart' in document.documentElement;
    if(is_touch_device) alert("touch is enabled!");
</script>
Alex W.
sumber
AFAIK, window.touch&& window.TouchEventhanya berfungsi untuk perangkat apple.
Starx
22
@vsync Modernizr adalah cara yang bagus untuk melakukan semua pengujian yang berguna bagi pengembang dalam pustaka yang dikelola, agar mereka tidak perlu ke Google setiap kali mereka perlu menguji fitur tertentu, seperti acara sentuh dan harus menemukan halaman ini. FYI ada build Modernizr khusus yang dapat Anda sesuaikan dengan tes yang Anda inginkan. Ini adalah cara yang bagus untuk menguji fitur dengan cara yang selalu sama di antara proyek, baik Anda menggunakan sintaks JS (yaitu: Modernizr.touch) atau kelas CSS (.touch .my-element {}). Saya pikir itu merupakan penghinaan terhadap kecerdasan manusia yang tidak mengakui bahwa kita dapat melakukan sesuatu tanpa menciptakan kembali roda setiap saat.
Alejandro García Iglesias
11
Yah, saya telah mengerjakan ratusan proyek dan saya tidak pernah membutuhkan hal seperti itu, dalam kebanyakan kasus yang Anda butuhkan hanyalah serangkaian tes yang sangat kecil, tidak pernah lebih dari 5 Saya akan mengatakan (dalam banyak kasus), jadi temukan saja 5 tersebut dan memasukkannya ke dalam kode Anda secara langsung, tidak perlu benar-benar membuka situs web Modernizer, membuat versi khusus, memasukkannya ke dalam halaman Anda, atau apa pun. Pengembang seharusnya tidak malas. Seorang pengembang web harus selalu memiliki pola pikir "bagaimana saya bisa membuat kode lebih ringan?" .. IMHO dan pengalaman bertahun-tahun. pengembang saat ini tampaknya suka menyertakan banyak skrip: /
vsync
2
Ada yang bilang malas. Saya katakan mengapa menemukan kembali roda? Bagaimana dengan saat perangkat / versi / platform baru muncul dan casing khusus Anda perlu diubah? Apakah Anda a) Mencoba mengerjakan sendiri kode deteksi kasus khusus, dan melakukan backport ke kode kustom Anda, memperolehnya kembali dalam proses, atau b) mendownload Modernizr versi terbaru dan memasukkannya? Saya tahu mana yang akan saya lakukan. +1 untuk GarciaWebDev.
Sc0ttyD
@ Sc0ttyD Preferensi pribadi saya adalah belajar membuat kode pada awalnya tanpa bergantung pada perpustakaan seperti Modernizr. Suatu hari Anda mungkin perlu menjadi orang yang mengkodekan perangkat baru dan Anda tidak ingin terjebak karena Anda tidak dapat melakukannya tanpa perpustakaan. Belum lagi, mungkin banyak orang yang tidak punya waktu untuk mempelajari perpustakaan baru.
Alex W
28

Pada 2017, kueri media CSS dari jawaban kedua masih tidak berfungsi di Firefox. Saya menemukan soluton untuk itu: -moz-touch-enabled


Jadi, inilah kueri media lintas-browser:

@media (-moz-touch-enabled: 1), (pointer:coarse) {
    .something {
        its: working;
    }
}
Sokołow
sumber
ini harus lebih tinggi dan jawaban yang disetujui. firefox sedang bekerja untuk mengimplementasikan spesifikasi, jadi -moz-touch-enabledtidak akan dibutuhkan segera
Dogoku
@ user3445853 OP menanyakan cara mendeteksi (melalui kueri media) perangkat dengan layar sentuh. Jika aturan "(pointer: none)" akan menjadi true, maka perangkat tidak memiliki layar sentuh untuk memastikannya. Tetapi seseorang harus mengkonfirmasi pendapat saya (atau tidak) :)
Sokołow
-moz-touch-enabledseharusnya tidak didukung di Firefox 58+. Seperti pada, solusi ini tidak mencakup Firefox 58-63 (karena Firefox 64+ mendukung kueri penunjuk). Sumber: developer.mozilla.org/en-US/docs/Web/CSS/@media/…
fgblomqvist
24

Sebenarnya ada media query untuk itu:

@media (hover: none) {  }

Selain Firefox, ini didukung dengan cukup baik . Safari dan Chrome menjadi browser yang paling umum di perangkat seluler, itu mungkin cukup sampai adopsi yang lebih besar.

Buzut
sumber
2
... dan dukungan akan datang di minggu-minggu berikutnya untuk FF juga.
retrovertigo
5

Ini akan berhasil. Jika tidak memberi tahu saya

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

edit: hover on-demand tidak lagi didukung

aleksa_95
sumber
3

Solusi ini akan berfungsi sampai CSS4 didukung secara global oleh semua browser. Ketika hari itu tiba gunakan saja CSS4. tetapi hingga saat itu, ini berfungsi untuk browser saat ini.

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:

cara lama:

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

cara yang lebih baru:

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

Kode di atas akan menambahkan kelas "is-touch" ke tag body jika perangkat memiliki layar sentuh. Sekarang lokasi mana pun di aplikasi web Anda di mana Anda akan memiliki css untuk: hover Anda dapat memanggilbody:not(.is-touch) the_rest_of_my_css:hover

sebagai contoh:

button:hover

menjadi:

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

Solusi ini menghindari penggunaan modernizer karena lib modernizer adalah perpustakaan yang sangat besar. Jika semua yang Anda coba lakukan adalah mendeteksi layar sentuh, Ini akan menjadi yang terbaik ketika ukuran sumber terkompilasi akhir adalah persyaratan.

Patrick W. McMahon
sumber
0

menambahkan layar sentuh kelas ke tubuh menggunakan JS atau jQuery

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

Saya dapat menyelesaikan masalah ini menggunakan ini

@media (hover:none), (hover:on-demand) { 
Your class or ID{
attributes
}    
}
Robin Mehdee
sumber
FYI, on-demandtelah dihapus dari spesifikasi dan dari browser: github.com/w3c/csswg-drafts/commit/…
retrovertigo