: pseudo-class aktif tidak berfungsi di safari seluler

109

Di Webkit di iPhone / iPad / iPod, menentukan gaya untuk: pseudo-class aktif untuk <a>tag tidak terpicu saat Anda mengetuk elemen tersebut. Bagaimana saya bisa memicunya? Kode contoh:

<style> 
a:active { 
    background-color: red;
}
</style>
<!-- snip -->
<a href="#">Click me</a>
Jesse Rusak
sumber

Jawaban:

238
<body ontouchstart="">
    ...
</body>

Diterapkan sekali saja, berbeda dengan setiap elemen tombol tampaknya memperbaiki semua tombol di halaman. Atau Anda bisa menggunakan pustaka JS kecil ini yang disebut ' Fastclick '. Ini mempercepat peristiwa klik pada perangkat sentuh dan menangani masalah ini juga.

wilsonpage
sumber
19
Bukankah cukup hanya menambahkan ontouchstarttanpa =""? (HTML5)
tinggalkan
2
Untuk pembaca selanjutnya, saya telah memposting demo di sini: http://jsbin.com/EjiWILe/3/ . Periksa fungsionalitas di perangkat iOS Anda.
mhulse
6
Bisakah Anda menjelaskan mengapa Anda menerapkan listener kosong ke body? Bagaimana cara kerjanya?
Maurizio Battaghini
2
Saya menggunakan: fokus, dan ini juga berfungsi untuk itu. Terima kasih untuk Sihirnya.
TecBrat
Saya mendapatkan halaman membeku di iOS 9.1 dan 9.3 menggunakan metode ini ... versi tersebut memiliki bug js, tetapi masih memiliki 0,5% pengguna di OS tersebut
Ruskin
55

Seperti jawaban lain telah menyatakan, iOS Safari tidak memicu :activepseudo-class kecuali peristiwa sentuh dilampirkan ke elemen tersebut, tetapi sejauh ini perilaku ini "ajaib". Saya menemukan uraian kecil ini di Perpustakaan Pengembang Safari yang menjelaskannya (penekanan milik saya):

Anda juga dapat menggunakan -webkit-tap-highlight-colorproperti CSS dalam kombinasi dengan menyetel peristiwa sentuh untuk mengonfigurasi tombol agar berperilaku mirip dengan desktop. Di iOS, peristiwa mouse dikirim begitu cepat sehingga status aktif atau nonaktif tidak pernah diterima. Oleh karena itu, status :activesemu hanya dipicu saat ada peristiwa sentuh yang disetel pada elemen HTML — misalnya, saat ontouchstart disetel pada elemen sebagai berikut:

<button class="action" ontouchstart=""
        style="-webkit-tap-highlight-color: rgba(0,0,0,0);">
    Testing Touch on iOS
</button>

Sekarang ketika tombol diketuk dan ditahan di iOS, tombol berubah menjadi warna yang ditentukan tanpa muncul warna abu-abu transparan di sekitarnya.

Dengan kata lain, menyetel ontouchstartacara (meskipun kosong) secara eksplisit memberi tahu browser untuk bereaksi terhadap acara sentuh.

Menurut pendapat saya, ini adalah perilaku yang salah, dan mungkin berasal dari masa ketika web "seluler" pada dasarnya tidak ada (lihat screenshot di halaman yang ditautkan untuk melihat apa yang saya maksud), dan semuanya berorientasi mouse. Menarik untuk dicatat bahwa peramban seluler lain yang lebih baru, seperti di Android, menampilkan status semu ': aktif' saat disentuh dengan baik, tanpa peretasan seperti yang diperlukan untuk iOS.

(Catatan samping: Jika Anda ingin menggunakan gaya kustom Anda sendiri di iOS, Anda juga dapat menonaktifkan kotak transparan abu-abu default yang digunakan iOS sebagai pengganti status :activesemu dengan menggunakan-webkit-tap-highlight-color properti CSS, seperti yang dijelaskan di halaman tertaut yang sama di atas .)


Setelah beberapa percobaan, solusi yang diharapkan dari pengaturan ontouchstartperistiwa pada <body>elemen yang semua peristiwa sentuh kemudian gelembung ke tidak bekerja sepenuhnya. Jika elemen terlihat di viewport saat halaman dimuat, maka itu berfungsi dengan baik, tetapi menggulir ke bawah dan menge-tap elemen yang berada di luar viewport tidak memicu status :activesemu seperti yang seharusnya. Jadi, bukan

<!DOCTYPE html>
<html><body ontouchstart></body></html>

lampirkan acara ke semua elemen alih-alih mengandalkan acara yang menggelembung ke badan (menggunakan jQuery):

$('body *').on('touchstart', function (){});

Namun, saya tidak mengetahui implikasi kinerja dari ini, jadi waspadalah.


EDIT: Ada satu kelemahan serius dengan solusi ini: bahkan menyentuh elemen saat menggulir halaman akan mengaktifkan status :activesemu. Sensitivitasnya terlalu kuat. Android memecahkan masalah ini dengan memberikan penundaan yang sangat kecil sebelum status ditampilkan, yang dibatalkan jika halaman di-scroll. Sehubungan dengan hal ini, saya sarankan menggunakan ini hanya pada elemen tertentu. Dalam kasus saya, saya sedang mengembangkan aplikasi web untuk digunakan di lapangan yang pada dasarnya adalah daftar tombol untuk menavigasi halaman dan mengirimkan tindakan. Karena seluruh halaman berisi cukup banyak tombol dalam beberapa kasus, ini tidak akan berhasil untuk saya. Namun, Anda dapat menyetel status :hoversemu untuk mengisi ini sebagai gantinya. Setelah menonaktifkan kotak abu-abu default, ini berfungsi dengan sempurna.

pengguna128216
sumber
6
Penjelasan bagus tentang mengapa dan bukan hanya bagaimana ! Terima kasih!
coderfin
6
Dipuji karena memberikan pemahaman kepada para dev, bukan hanya resep "ajaib". Ini jauh lebih informatif daripada yang lain; terima kasih telah menulis ini untuk kami.
user508633
Suara positif untuk penjelasan detail + peringatan. Ini harus menjadi jawaban yang benar.
Master of Ducks
39

Tambahkan event handler untuk ontouchstart di tag <a> Anda. Ini menyebabkan CSS bekerja secara ajaib.

<a ontouchstart="">Click me</a>
Jesse Rusak
sumber
3
Maaf, ini jawaban lama, tapi mengapa ini berhasil? Saya tidak keberatan "secara ajaib" sebagai alasan, tetapi jika Anda dapat menjelaskan mengapa ini berhasil, saya ingin membaca lebih detail.
mhulse
1
@mhulse Saya juga ingin tahu alasannya.
Jesse Rusak
Ha! Kami berada di perahu yang sama. Saya akan mencoba melakukan penelitian dan memposting kembali ke sini tautan ke dokumen (semi-) resmi tentang masalah tersebut. Saya suka teknik ini berhasil, saya hanya bertanya-tanya mengapa?
mhulse
7

Ini bekerja untuk saya:

document.addEventListener("touchstart", function() {},false);

Catatan: jika Anda melakukan trik ini, ada baiknya juga menghapus tap default – warna highlight Mobile Safari berlaku menggunakan aturan CSS berikut.

html {
    -webkit-tap-highlight-color: rgba(0,0,0,0);
}
dhqvinh
sumber
5

Pada 8 Des 2016, jawaban yang diterima (<body ontouchstart="">...</body> ) tidak berfungsi untuk saya di Safari 10 (iPhone 5s): Peretasan itu hanya berfungsi untuk elemen-elemen yang terlihat pada pemuatan halaman.

Namun, menambahkan:

<script type='application/javascript'>
  document.addEventListener("touchstart", function() {}, false);
</script>

agar headberfungsi seperti yang saya inginkan, dengan sisi negatifnya bahwa sekarang semua peristiwa sentuh selama pengguliran juga memicu keadaan :activesemu pada elemen yang disentuh. (Jika ini menjadi masalah bagi Anda, Anda dapat mempertimbangkan solusi FighterJet :hover .)

Ali
sumber
4
//hover for ios
-webkit-tap-highlight-color: #ccc;

Ini berfungsi untuk saya, tambahkan ke CSS Anda pada elemen yang ingin Anda sorot

Mata merah
sumber
3

Apakah Anda menggunakan semua pseudo-class atau hanya satu? Jika Anda menggunakan setidaknya dua, pastikan urutannya benar atau semuanya rusak:

a:link
a:visited
a:hover
a:active

..di urutan itu. Selain itu, Jika Anda hanya menggunakan: aktif, tambahkan tautan:, meskipun Anda tidak menatanya.

tahdhaze09
sumber
tip bagus tentang keteraturan menjadi penting saat menata kelas semu.
brianarpie
1

Saya telah menerbitkan alat yang seharusnya menyelesaikan masalah ini untuk Anda.

Di permukaan masalahnya terlihat sederhana, tetapi pada kenyataannya perilaku sentuh & klik perlu disesuaikan secara ekstensif, termasuk fungsi batas waktu dan hal-hal seperti "apa yang terjadi saat Anda menggulir daftar tautan" atau "apa yang terjadi ketika Anda menekan tautan lalu gerakkan mouse / jari menjauh dari area aktif "

Ini harus menyelesaikan semuanya sekaligus: https://www.npmjs.com/package/active-touch

Anda harus menetapkan: gaya aktif Anda ke kelas .active atau memilih nama kelas Anda sendiri. Secara default, skrip akan berfungsi dengan semua elemen tautan, tetapi Anda dapat menimpanya dengan susunan pemilih Anda sendiri.

Umpan balik dan kontribusi yang jujur ​​dan bermanfaat sangat dihargai!

dmitrizzle
sumber
2
Library tersebut menambahkan 9 event listener (non pasif) ke setiap elemen link tetapi tidak memanggil removeEventListener - ini akan menjadi kelemahan besar untuk aplikasi satu halaman menurut saya
Drenai
1
Terima kasih Ryan. Saya belum mendukung atau menggunakan kode ini selama lebih dari setahun; Aku akan menurunkannya. Setelah beberapa pemikiran dan eksperimen, saya mengubah desain aplikasi alih-alih mencoba memaksa interaksi yang tidak diperhitungkan atau dipikirkan oleh browser.
dmitrizzle
1

Bagi yang tidak ingin menggunakan ontouchstart, Anda bisa menggunakan kode ini

<script>
 document.addEventListener("touchstart", function(){}, true);
</script>
Noob Dev
sumber
1

Saya mencoba jawaban ini dan variannya, tetapi tampaknya tidak ada yang bekerja dengan andal (dan saya tidak suka mengandalkan 'sihir' untuk hal-hal seperti ini). Jadi saya melakukan yang berikut ini, yang berfungsi dengan sempurna di semua platform, bukan hanya Apple:

  1. Deklarasi css Berganti nama yang digunakan :activeuntuk .active.
  2. Membuat daftar semua elemen yang terpengaruh dan menambahkan pointerdown/mousedown/touchstartpenangan peristiwa untuk menerapkan .activekelas dan pointerup/mouseup/touchendpenangan peristiwa untuk menghapusnya. Menggunakan jQuery:

    let controlActivationEvents = window.PointerEvent ? "pointerdown" : "touchstart mousedown";
    let controlDeactivationEvents = window.PointerEvent ? "pointerup pointerleave" : "touchend mouseup mouseleave";
    
    let clickableThings = '<comma separated list of selectors>';
    $(clickableThings).on(controlActivationEvents,function (e) {
        $(this).addClass('active');
    }).on(controlDeactivationEvents, function (e) {
        $(this).removeClass('active');
    });

Ini agak membosankan, tetapi sekarang saya memiliki solusi yang tidak terlalu rentan terhadap kerusakan di antara versi Apple OS. (Dan siapa yang butuh sesuatu seperti pemutusan ini?)

daffinm
sumber
Saya pikir itu memberikan jawaban atas pertanyaan itu. Tampaknya tidak ada cara yang dapat diandalkan untuk membuat: kelas semu aktif berfungsi di Safari seluler. Tetapi ini dapat ditiru dengan andal menggunakan solusi yang telah saya berikan. Saya telah melakukan ini di aplikasi saya dan berfungsi dengan sempurna di semua platform. Dan saya telah menambahkan kode melalui klarifikasi.
daffinm
0

Solusinya adalah mengandalkan :targetalih-alih :active:

<style> 
a:target { 
    background-color: red;
}
</style>
<!-- snip -->
<a id="click-me" href="#click-me">Click me</a>

Gaya akan dipicu saat jangkar ditargetkan oleh url saat ini, yang kuat bahkan di seluler. Kekurangannya adalah Anda membutuhkan tautan lain untuk menghapus jangkar di url. Contoh lengkapnya:

a:target { 
    background-color: red;
}
<a id="click-me" href="#click-me">Click me</a>
<a id="clear" href="#">Clear</a>

rgmt
sumber
-3

Tidak 100% terkait dengan pertanyaan ini, tetapi Anda juga dapat menggunakan css sibling hack untuk melakukannya

HTML

<input tabindex="0" type="checkbox" id="145"/>
<label for="145"> info</label>
<span> sea</span>

SCSS

input {
    &:checked + label {
      background-color: red;
    }
  }

Jika Anda ingin menggunakan tooltip html / css murni

span {
  display: none;
}
input {
    &:checked ~ span {
      display: block;
    }
  }
Seeliang
sumber
-6
<!DOCTYPE html>

<html lang="en">

<head>
<meta charset="utf-8">

<title></title>

<style>
        a{color: red;}
        a:hover{color: blue;}
</style>
</head>

<body>

        <div class="main" role="main">
                <a href="#">Hover</a>
        </div>

</body>
</html>
TroyM
sumber
1
Sesuai FAQ, tanda tangan dan promosi diri tidak diperbolehkan.
LittleBobbyTables - Au Revoir