Bagaimana mencegah efek hover lengket untuk tombol pada perangkat sentuh

144

Saya telah membuat korsel dengan tombol sebelumnya dan selanjutnya yang selalu terlihat. Tombol-tombol ini memiliki status hover, berubah menjadi biru. Pada perangkat sentuh, seperti iPad, status hover lengket, sehingga tombol tetap biru setelah mengetuknya. Saya tidak menginginkan itu.

  • Saya dapat menambahkan no-hoverkelas ontouchenduntuk setiap tombol, dan membuat CSS saya seperti ini: button:not(.no-hover):hover { background-color: blue; }tetapi itu mungkin sangat buruk untuk kinerja, dan tidak menangani perangkat seperti Chromebook Pixel (yang memiliki layar sentuh dan mouse) dengan benar.

  • Saya bisa menambahkan touchkelas ke documentElementdan membuat CSS saya seperti ini: html:not(.touch) button:hover { background-color: blue; }Tapi itu juga tidak berfungsi dengan baik pada perangkat dengan sentuhan dan mouse.

Yang saya inginkan adalah menghapus status hover ontouchend . Tapi sepertinya itu tidak mungkin. Memfokuskan elemen lain tidak menghapus status hover. Mengetuk elemen lain secara manual, tetapi sepertinya saya tidak dapat memicunya di JavaScript.

Semua solusi yang saya temukan tampaknya tidak sempurna. Apakah ada solusi yang sempurna?

Chris
sumber

Jawaban:

55

Anda dapat menghapus status hover dengan menghapus sementara tautan dari DOM. Lihat http://testbug.handcraft.com/ipad.html


Di dalam CSS Anda memiliki:

:hover {background:red;}

Di JS Anda memiliki:

function fix()
{
    var el = this;
    var par = el.parentNode;
    var next = el.nextSibling;
    par.removeChild(el);
    setTimeout(function() {par.insertBefore(el, next);}, 0)
}

Dan kemudian dalam HTML Anda, Anda memiliki:

<a href="#" ontouchend="this.onclick=fix">test</a>
Darren Cook
sumber
3
@ Chris Good point, saya mengubah contoh untuk mengatur handler onclick di event ontouchend.
Sjoerd Visscher
4
Harap pertimbangkan untuk menambahkan kode demonstratif minimal ke jawaban Anda. Terima kasih! stackoverflow.com/help/how-to-answer
2540625
1
@ SojoerdVisscher Saya telah menempelkannya. StackOverflow menyukai kode yang ada dalam jawaban, karena tautan dapat hilang. (Dan dalam hal ini diperlukan tidak hanya mengklik, tetapi kemudian melihat sumbernya, dan mencari tahu bit mana yang merupakan teknik yang dimaksud.)
Darren Cook
2
@KevinBorders ya pada beberapa perangkat, waktu tunda antara penghapusan dan masukkan kembali elemen bisa sangat terlihat. Sayangnya, saya menemukan di perangkat Android 4.4 saya yang melakukan ini tanpa setTimeout tidak berfungsi.
Rodney
1
Idenya menarik, tetapi saya merasa agak tersentak dan tidak didukung secara luas pada semua perangkat sentuh. Saya lebih suka solusi yang kurang invasif berdasarkan deteksi dukungan sentuh dan css murni seperti ini stackoverflow.com/a/39787268/885464
Lorenzo Polidori
83

Setelah CSS Media Query Level 4 diimplementasikan, Anda akan dapat melakukan ini:

@media (hover: hover) {
    button:hover {
        background-color: blue;
    }
}

Atau dalam bahasa Inggris: "Jika browser mendukung hovering yang benar / benar / nyata / tidak-emulasi (mis. Memiliki perangkat input primer seperti mouse), maka terapkan gaya ini ketika buttons berada di atas."

Karena bagian dari Kueri Media Level 4 ini sejauh ini hanya diterapkan di Chrome yang berdarah, saya menulis polyfill untuk mengatasinya. Dengan menggunakannya, Anda dapat mengubah CSS futuristik di atas menjadi:

html.my-true-hover button:hover {
    background-color: blue;
}

(Variasi pada .no-touchteknik) Dan kemudian menggunakan beberapa sisi-klien JavaScript dari polyfill yang sama yang mendeteksi dukungan untuk melayang, Anda dapat mengubah keberadaan my-true-hoverkelas sesuai:

$(document).on('mq4hsChange', function (e) {
    $(document.documentElement).toggleClass('my-true-hover', e.trueHover);
});
cvrebert
sumber
Terima kasih! Untuk tujuan saya ini tampaknya didukung di sebagian besar browser caniuse.com/#search=media%20queries dan berfungsi dengan sangat baik, terima kasih!
ragamufin
3
Anda perlu melihat caniuse.com/#feat=css-media-interaction sebagai gantinya dan Anda akan melihat itu tidak didukung di Firefox dan IE11 :( jadi Anda memerlukan polyfill
CherryDT
Tampaknya polyfill tidak lagi didukung (repo diarsipkan) dan memerlukan jQuery ...
amoebe
Ini sekarang didukung secara luas di peramban seluler, dan berfungsi seperti pesona. Saya pikir itu harus menjadi jawaban yang diterima.
Trevor Burnham
Ini jelas yang paling mudah diterapkan dan jawaban terbaik. Bekerja di Firefox di Android Mobile dan PC. Tidak yakin tentang perangkat dual touch dan mouse.
HalfMens
28

Ini adalah masalah umum tanpa solusi sempurna. Perilaku melayang berguna dengan mouse dan sebagian besar merugikan dengan sentuhan. Yang menjadi masalah adalah perangkat yang mendukung sentuhan dan mouse (secara bersamaan, tidak kurang!) Seperti Chromebook Pixel dan Surface.

Solusi terbersih yang saya temukan adalah hanya mengaktifkan perilaku melayang jika perangkat tidak dianggap mendukung input sentuh.

var isTouch =  !!("ontouchstart" in window) || window.navigator.msMaxTouchPoints > 0;

if( !isTouch ){
    // add class which defines hover behavior
}

Memang, Anda kehilangan kursor pada perangkat yang mungkin mendukungnya. Namun, terkadang hover dampak lebih dari tautan itu sendiri, mis. Mungkin Anda ingin menampilkan menu ketika sebuah elemen di-hover. Pendekatan ini memungkinkan Anda untuk menguji keberadaan sentuhan dan mungkin secara kondisional melampirkan peristiwa yang berbeda.

Saya sudah menguji ini di iPhone, iPad, Chromebook Pixel, Surface, dan berbagai perangkat Android. Saya tidak dapat menjamin bahwa itu akan berfungsi ketika input sentuh USB umum (seperti stylus) ditambahkan ke dalam mix.

Tim Medora
sumber
1
Luar biasa, ini bekerja untuk saya, tidak seperti komunitas wiki / Darren Cook.
Jannik
1
Jawaban yang bagus. Ini adalah solusi yang serupa: stackoverflow.com/a/39787268/885464
Lorenzo Polidori
11

Dengan Modernizr Anda dapat menargetkan hover Anda secara khusus untuk perangkat tanpa sentuhan:

(Catatan: ini tidak berjalan pada sistem potongan StackOverflow, periksa jsfiddle sebagai gantinya)

/* this one is sticky */
#regular:hover, #regular:active {
  opacity: 0.5;
}

/* this one isn't */
html.no-touch #no-touch:hover, #no-touch:active {
  opacity: 0.5;
}

Catatan yang :activetidak perlu ditargetkan .no-touchkarena itu berfungsi seperti yang diharapkan pada ponsel dan desktop.

rachel
sumber
Ini adalah jawaban terbaik IMO TAPI contohnya salah. Ini menunjukkan status hover yang sama untuk perangkat sentuh dan non-sentuh. Seharusnya hanya menerapkan status hover jika .no-touchada pada htmltag. Kalau tidak, jawaban ini mendapat cap persetujuan saya.
morrisbret
2
Masalahnya adalah sekarang perangkat yang mendukung mouse yang memiliki layar sentuh ada di mana-mana, Anda tidak bisa lagi mengandalkan metode ini. Namun saya tidak bisa melihat banyak cara lain untuk melakukannya ... ini cukup dilematis
dudewad
Saya kira salah satu cara untuk melakukannya adalah menggunakan Modernizr dan juga perpustakaan seperti mobile-detect.js untuk memastikan itu baik ponsel atau tablet.
Gavin
Anda adalah penyelamat, terima kasih banyak, ini bekerja dengan sempurna untuk perangkat seluler
Shivam
9

Anda dapat mengesampingkan efek hover untuk perangkat yang tidak mendukung hover. Suka:

.my-thing {
    color: #BADA55;
}

.my-thing:hover {
    color: hotpink;
}

@media (hover: none) {
    .my-thing {
        color: #BADA55;
    }
}

Diuji dan diverifikasi di iOS 12

Kiat tip untuk https://stackoverflow.com/a/50285058/178959 untuk menunjukkan ini.

Organik panda
sumber
Ini adalah solusi yang lebih modern, tidak perlu memanipulasi javascript atau DOM, memiliki dukungan browser penuh (kecuali IE) dan harus menjadi jawaban yang diterima.
funkju
8
$("#elementwithhover").click(function() { 
  // code that makes element or parent slide or otherwise move out from under mouse. 

  $(this).clone(true).insertAfter($(this));
  $(this).remove();
});
Verard Sloggett
sumber
Anda dapat meningkatkan jawaban ini dengan menggunakan pada () alih-alih mengklik (). Dengan menghapus elemen dari DOM dan memasangnya kembali, saya kehilangan acara klik saya. Ketika saya menulis ulang fungsi saya dengan aktif, mengikat elemen, lalu menghapus dan menambahkan berfungsi. Sebagai contoh: `$ ('body'). On ('klik', '# elementwithhover', function () {// clone, insertafter, hapus}); Saya akan memilih ini jika Anda melakukan perubahan itu.
Will Lanni
clone true mempertahankan event klik pada elemenet baru menggantikan elemen dengan hover yang macet. elemen asli sedang dihapus dari dom setelah dikloning.
Verard Sloggett
awesome bro, 10x
Kaloyan Stamatov
Jam mencari perbaikan dan ini akhirnya memberikan satu. Terima kasih banyak!
phil917
8

Dari 4 cara menangani sticky hover di ponsel : Ini cara untuk menambah atau menghapus " can touch" kelas secara dinamis ke dokumen berdasarkan tipe input pengguna saat ini. Ini bekerja dengan perangkat hybrid juga di mana pengguna dapat beralih antara sentuhan dan mouse / trackpad:

<script>

;(function(){
    var isTouch = false //var to indicate current input type (is touch versus no touch) 
    var isTouchTimer 
    var curRootClass = '' //var indicating current document root class ("can-touch" or "")

    function addtouchclass(e){
        clearTimeout(isTouchTimer)
        isTouch = true
        if (curRootClass != 'can-touch'){ //add "can-touch' class if it's not already present
            curRootClass = 'can-touch'
            document.documentElement.classList.add(curRootClass)
        }
        isTouchTimer = setTimeout(function(){isTouch = false}, 500) //maintain "istouch" state for 500ms so removetouchclass doesn't get fired immediately following a touch event
    }

    function removetouchclass(e){
        if (!isTouch && curRootClass == 'can-touch'){ //remove 'can-touch' class if not triggered by a touch event and class is present
            isTouch = false
            curRootClass = ''
            document.documentElement.classList.remove('can-touch')
        }
    }

    document.addEventListener('touchstart', addtouchclass, false) //this event only gets called when input type is touch
    document.addEventListener('mouseover', removetouchclass, false) //this event gets called when input type is everything from touch to mouse/ trackpad
})();

</script>
kepulan coco
sumber
Ini adalah cara terbaik yang saya temukan, ditambah jika Anda meningkatkan timer ke 1000 ms Anda juga dapat menutupi pers lama, lihat di sini . Barang bagus!
lowtechsun
3

Saya akan memposting solusi saya sendiri, tetapi memeriksa apakah seseorang sudah mempostingnya, saya menemukan bahwa @Rodney hampir melakukannya. Namun, dia melewatkannya satu krusial terakhir yang membuatnya tidak menarik, setidaknya dalam kasus saya. Maksud saya, saya juga mengambil .fakeHoverpenambahan / penghapusan kelas yang sama mouseenterdan mouseleavedeteksi acara, tetapi itu saja, per se , bertindak hampir persis seperti "asli" :hover. Maksud saya: ketika Anda mengetuk elemen di meja Anda, itu tidak akan mendeteksi bahwa Anda telah "meninggalkannya" - dengan demikian menjaga status "pemalsuan".

Apa yang saya lakukan hanyalah mendengarkan click, jadi ketika saya "mengetuk" tombolnya, saya secara manual menyalakan a mouseleave.

Si, ini kode terakhir saya:

.fakeHover {
    background-color: blue;
}


$(document).on('mouseenter', 'button.myButton',function(){
    $(this).addClass('fakeHover');
});

$(document).on('mouseleave', 'button.myButton',function(){
    $(this).removeClass('fakeHover');
});

$(document).on('button.myButton, 'click', function(){
    $(this).mouseleave();
});

Dengan cara ini Anda menjaga hoverfungsionalitas Anda yang biasa saat menggunakan mouse saat hanya "melayang" pada tombol Anda. Yah, hampir semuanya: satu-satunya kelemahannya adalah, setelah mengklik tombol dengan mouse, itu tidak akan dalam hoverkeadaan. Sama seperti jika Anda mengklik dan dengan cepat mengeluarkan pointer dari tombol. Tetapi dalam kasus saya, saya bisa hidup dengan itu.

Pere
sumber
2

Inilah yang saya temukan sejauh ini setelah mempelajari sisa jawaban. Itu harus dapat mendukung pengguna sentuh saja, mouse saja atau hybrid.

Buat kelas hover terpisah untuk efek hover. Secara default, tambahkan kelas hover ini ke tombol kami.

Kami tidak ingin mendeteksi keberadaan dukungan sentuh dan menonaktifkan semua efek hover dari awal. Seperti yang disebutkan oleh orang lain, perangkat hybrid semakin populer; orang mungkin memiliki dukungan sentuh tetapi ingin menggunakan mouse dan sebaliknya. Oleh karena itu, hapus saja kelas hover ketika pengguna benar-benar menyentuh tombol.

Masalah selanjutnya adalah, bagaimana jika pengguna ingin kembali menggunakan mouse setelah menyentuh tombol? Untuk mengatasinya, kita perlu mencari momen yang tepat untuk menambahkan kembali kelas hover yang telah kita hapus.

Namun, kami tidak dapat menambahkannya kembali segera setelah menghapusnya, karena status hover masih aktif. Kami mungkin tidak ingin menghancurkan dan membuat ulang seluruh tombol juga.

Jadi, saya berpikir untuk menggunakan algoritma sibuk-menunggu (menggunakan setInterval) untuk memeriksa status hover. Setelah negara melayang dinonaktifkan, kita kemudian dapat menambahkan kembali kelas melayang dan menghentikan sibuk menunggu, membawa kita kembali ke keadaan awal di mana pengguna dapat menggunakan mouse atau sentuhan.

Saya tahu sibuk-menunggu tidak terlalu bagus tapi saya tidak yakin apakah ada acara yang tepat. Saya sudah mempertimbangkan untuk menambahkannya kembali di acara mouseleave, tapi itu tidak terlalu kuat. Misalnya, ketika peringatan muncul setelah tombol disentuh, posisi mouse bergeser tetapi acara mouseleave tidak terpicu.

var button = document.getElementById('myButton');

button.ontouchstart = function(e) {
  console.log('ontouchstart');
  $('.button').removeClass('button-hover');
  startIntervalToResetHover();
};

button.onclick = function(e) {
  console.log('onclick');
}

var intervalId;

function startIntervalToResetHover() {
  // Clear the previous one, if any.
  if (intervalId) {
    clearInterval(intervalId);
  }
  
  intervalId = setInterval(function() {
    // Stop if the hover class already exists.
    if ($('.button').hasClass('button-hover')) {
      clearInterval(intervalId);
      intervalId = null;
      return;
    }
    
    // Checking of hover state from 
    // http://stackoverflow.com/a/8981521/2669960.
    var isHovered = !!$('.button').filter(function() {
      return $(this).is(":hover");
    }).length;
    
    if (isHovered) {
      console.log('Hover state is active');
    } else {
      console.log('Hover state is inactive');
      $('.button').addClass('button-hover');
      console.log('Added back the button-hover class');
      
      clearInterval(intervalId);
      intervalId = null;
    }
  }, 1000);
}
.button {
  color: green;
  border: none;
}

.button-hover:hover {
  background: yellow;
  border: none;
}

.button:active {
  border: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id='myButton' class='button button-hover'>Hello</button>

Sunting: Pendekatan lain yang saya coba adalah menelepon e.preventDefault()dalam ontouchstart atau ontouchend. Tampaknya untuk menghentikan efek hover ketika tombol disentuh, tetapi juga menghentikan animasi klik tombol dan mencegah fungsi onclick dipanggil saat tombol disentuh, jadi Anda harus memanggil mereka secara manual di ontouchstart atau ontouchend handler. Bukan solusi yang sangat bersih.

Kevin Lee
sumber
1

Itu membantu saya: tautan

function hoverTouchUnstick() {
    // Check if the device supports touch events
    if('ontouchstart' in document.documentElement) {
        // Loop through each stylesheet
        for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
            var sheet = document.styleSheets[sheetI];
            // Verify if cssRules exists in sheet
            if(sheet.cssRules) {
                // Loop through each rule in sheet
                for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
                    var rule = sheet.cssRules[ruleI];
                    // Verify rule has selector text
                    if(rule.selectorText) {
                        // Replace hover psuedo-class with active psuedo-class
                        rule.selectorText = rule.selectorText.replace(":hover", ":active");
                    }
                }
            }
        }
    }
}
mineroot
sumber
Anda perlu memanggil hoverTouchUnstick () sekali dari pengendali event ontouchstart global. Dan solusi ini akan bekerja dengan sempurna.
Jusid
1

Tambahkan kode JS ini ke halaman Anda:

document.body.className = 'ontouchstart' in document.documentElement ? '' : 'hover';

sekarang di CSS Anda sebelum setiap hover menambahkan kelas hover seperti ini:

.hover .foo:hover {}

Jika perangkat disentuh, kelas tubuh akan kosong, jika tidak kelasnya akan mengambang dan aturan diterapkan!

Ali
sumber
Tidak bekerja untuk saya, tetapi ini berhasil:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster
1

Saya bisa menambahkan ontouchend kelas no-hover untuk setiap tombol, dan membuat CSS saya seperti> ini: tombol: tidak (.tidak ada-hover): hover {background-color: blue; } tetapi itu mungkin sangat buruk untuk kinerja, dan tidak menangani> perangkat seperti Chromebook Pixel (yang memiliki layar sentuh dan mouse)> dengan benar.

Ini adalah titik awal yang tepat. Langkah berikutnya: menerapkan / menghapus kelas nohover pada acara-acara berikut (demo dengan jQuery)

buttonelement
 .on("touchend touchcancel",function(){$(this).addClass("nohover")})
 .on("touchstart mouseover",function({$(this).removeClass("nohover")});   

Perhatian: Jika Anda ingin menerapkan kelas lain ke elemen tombol, the: not (.nohover) di CSS tidak akan berfungsi lagi seperti yang diharapkan. Daripada Anda harus menambahkan definisi yang terpisah dengan nilai default dan! Tag penting untuk menimpa gaya hover: .nohover {background-color: white! Important}

Ini bahkan harus menangani perangkat seperti Chromebook Pixel (yang memiliki layar sentuh dan mouse) dengan benar! Dan saya tidak berpikir, bahwa ini adalah pembunuh kinerja utama ...

Sascha Hendel
sumber
1

Solusi yang berhasil bagi saya:

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

Tambahkan kode ini ke stylesheet Anda.

Saya ingin menyingkirkan latar belakang abu-abu yang muncul di iOS Safari ketika tautan diklik. Tetapi tampaknya melakukan lebih banyak. Sekarang mengklik tombol (dengan :hoverpseudoclass!) Akan segera dibuka! Saya hanya mengujinya di iPad, saya tidak tahu apakah itu akan berfungsi pada perangkat lain.

Leon Vogler
sumber
1

Saya pikir saya telah menemukan solusi elegan (minimum js) untuk masalah yang sama:

Menggunakan jQuery, Anda dapat memicu melayang di badan (atau elemen lainnya), menggunakan .mouseover()

Jadi saya cukup melampirkan penangan ini ke acara elemen ontouchendseperti:

var unhover = function() {
  $("body").mousover();  
};
.hoverable {
  width: 100px;
  height: 100px;
  background: teal;
  cursor: pointer;
}

.hoverable:hover {
  background: pink;
}
<div class="hoverable" ontouchend={unhover}></div>

Ini, bagaimanapun, hanya menghapus: letakkan pseudoclass dari elemen setelah beberapa peristiwa sentuhan lainnya telah dipicu, seperti menggesek atau sentuhan lain

Ian Averno
sumber
1
Untuk cuplikan kode Anda, kotak masih tetap berwarna merah muda setelah saya menyentuhnya. Saya kira Anda tidak benar-benar menyelesaikan masalah yang diajukan dalam pertanyaan ini?
Kevin Lee
Solusi ini tidak berfungsi. Pertama, Anda menggunakan metode yang salah untuk memanggil suatu acara, Anda harus menggunakan .trigger () . Kedua, tidak bekerja pada safari seluler.
xHocquet
1

Saya punya solusi bagus yang ingin saya bagikan. Pertama, Anda perlu mendeteksi apakah pengguna di ponsel seperti ini:

var touchDevice = /ipad|iphone|android|windows phone|blackberry/i.test(navigator.userAgent.toLowerCase());

Kemudian tambahkan saja:

if (!touchDevice) {
    $(".navbar-ul").addClass("hoverable");
}

Dan dalam CSS:

.navbar-ul.hoverable li a:hover {
    color: #fff;
}
Michał Reszka
sumber
2
Tidak berfungsi pada perangkat hybrid, misal PC layar sentuh Windows.
cspolton
1

Saya mengalami masalah yang sama, aplikasi saya kompatibel untuk semua ukuran layar memiliki banyak efek hover di ukuran layar desktop / mouse , dan kemudian saya menyadari bahwa perangkat berbasis sentuhan menyebabkan kondisi yang dikenal sebagai lengket -hover dan itu adalah rintangan bagi aplikasi untuk bekerja dengan baik untuk pengguna perangkat berbasis sentuhan.

Kami memanfaatkan SCSS di aplikasi kami. dan saya mendefinisikan mixin untuk menjaga perangkat berbasis sentuhan.

@mixin hover-support {
  @media not all and (pointer: coarse) {
    &:hover {
      @content;
    }
  }
}

dan kemudian saya menempatkan semua kelas css saya di bawah cuplikan yang disebutkan di bawah ini.

   @include hover-support() {
    // Your css-classes or css that you want to apply on those devices that support hover.
   }

Sebagai contoh, kami memiliki kelas untuk menggerakkan ikon, dan yang digunakan untuk memicu setelah kami mengarahkan ikon seperti yang Anda lihat dari css, tetapi di perangkat berbasis sentuhan itu dipengaruhi oleh efek hover yang lengket dan kemudian saya menempatkannya di dalam @ termasuk dukungan hover () untuk memastikan bahwa hover hanya berlaku untuk perangkat yang mendukung hover.

@include hover-support() {
  .animate-icon {
    -webkit-transition: all 0.2s;
    transition: all 0.2s;
    &:hover {
      transform: scale(1.3);
      filter: brightness(85%);
      cursor: pointer;
    }
  }
}
Divyanshu Rawat
sumber
1

Berikut adalah beberapa kode JavaScript sederhana yang tidak mengharuskan pengembang untuk mengedit CSS atau menulis aturan CSS baru. Saya menulis ini untuk tombol Bootstrap class="btn", tetapi akan bekerja dengan tombol apa pun yang memiliki nama kelas tertentu.

Langkah-langkahnya adalah:

  1. tentukan apakah ini perangkat sentuh
  2. jika ya, lakukan iterasi atas setiap aturan CSS di document.styleSheets
  3. hapus aturan apa pun yang mengandung keduanya .btndan:hover

Penghapusan semua .btn :hoveraturan CSS memastikan bahwa tidak akan ada efek melayang visual pada tombol.

Langkah 1: Deteksi Perangkat Sentuh

Periksa kueri media untuk mengetahui keberadaan (hover: none):

    const hasMatchMedia = typeof window.matchMedia !== 'undefined';
    /**
     * determine if device is touch-capable
     * true - device is touch-capable
     * false - device is not touch-capable
     * null - unable to determine touch capability
     * @return {null|boolean}
     */
    const hasTouch = () => {
      if (hasMatchMedia) {
        return window.matchMedia('(hover: none)').matches;
      }
      return null;
    };

Langkah 2: Hapus Aturan CSS yang Mengandung `btn` dan`: hover`

    /**
     * remove all CSS rules contaning both '.btn' and ':hover'
     * @return {number} count of rules deleted
     */
    function removeBtnHovers () {

      let rulesDeleted = 0;

      // recursively delete '.btn:hover' rules
      function recursiveDelete (rules, styleSheet) {

        if (typeof rules === 'undefined' ||
          typeof rules.length === 'undefined' ||
          rules.length <= 0) {
          return;
        }

        // iterate in reverse order,
        // deleting any rule containing both '.btn' and ':hover'
        const ruleLen = rules.length;
        for (let i = ruleLen - 1; i >= 0; i--) {
          const rule = rules[i];
          if (typeof rule.cssRules === 'undefined') {
            // a standard rule, evaluate it
            const cssText = rule.cssText;
            if (typeof cssText === 'string' &&
              cssText.includes('.btn') &&
              cssText.includes(':hover')) {
              styleSheet.deleteRule(i);
              rulesDeleted++;
            }
          } else {
            // rule contains cssRules, iterate over them
            recursiveDelete(rule.cssRules, rule);
          }
        }
      }

      // iterate over all style sheets in document
      for (const styleSheet of document.styleSheets) {
        let rules = styleSheet.cssRules;
        if (!rules) { continue; }
        recursiveDelete(rules, styleSheet);
      }
      return rulesDeleted;
    }

Kode lengkap ada di GitHub dan npm .

Demo langsung di terrymorse.com .

terrymorse
sumber
Tidakkah ini juga menghilangkan efek hover untuk perangkat layar sentuh dengan mouse / trackpad?
Jensei
@Jensei Mungkin. Aturan hover dihapus jika perangkat cocok @media (hover:none), atau ketika pengguna pertama kali menyentuh layar. Anda dapat mencobanya di halaman demo langsung untuk memastikan.
terrymorse
0

Anda dapat mengatur warna latar belakang pada :activestatus dan memberikan :focus latar belakang defaut.

jika Anda mengatur warna latar melalui onfocus/ontouch, gaya warna akan tetap setelah :focusstatus hilang.
Anda perlu mengatur ulang onblurjuga untuk mengembalikan bg cacat saat fokus hilang.

G-Cyrillus
sumber
Tetapi saya ingin mempertahankan efek hover untuk pengguna mouse.
Chris
: arahkan dan: aktif dapat menerima CSS yang sama, aktif: fokus Anda memiliki masalah. Sebenarnya, jika Anda mengatur warna latar belakang melalui onfocus, gaya warna tetap ada setelah fokus hilang. Anda perlu reset pada onlur juga untuk mengembalikan bg cacat
G-Cyrillus
0

Ini bekerja untuk saya: letakkan hover styling di kelas baru

.fakehover {background: red}

Kemudian tambahkan / hapus kelas saat dan ketika dibutuhkan

$(".someclass > li").on("mouseenter", function(e) {
  $(this).addClass("fakehover");
});
$(".someclass > li").on("mouseleave", function(e) {
  $(this).removeClass("fakehover");
});

Ulangi untuk touchstart dan touchend acara. Atau acara apa pun yang Anda suka untuk mendapatkan hasil yang diinginkan, misalnya saya ingin efek hover diaktifkan di layar sentuh.

Rodney
sumber
0

Berdasarkan jawaban Darren Cooks yang juga berfungsi jika Anda memindahkan jari Anda ke elemen lain.

Lihat Menemukan elemen jari aktif selama acara touchend

jQuery(function() {
    FastClick.attach(document.body);
});
// Prevent sticky hover effects for buttons on touch devices
// From https://stackoverflow.com/a/17234319
//
//
// Usage:
// <a href="..." touch-focus-fix>..</a>
//
// Refactored from a directive for better performance and compability
jQuery(document.documentElement).on('touchend', function(event) {
  'use strict';

  function fix(sourceElement) {
    var el = $(sourceElement).closest('[touch-focus-fix]')[0];
    if (!el) {
      return;
    }
    var par = el.parentNode;
    var next = el.nextSibling;
    par.removeChild(el);
    par.insertBefore(el, next);
  }

  fix(event.target);
  var changedTouch = event.originalEvent.changedTouches[0];
  // http://www.w3.org/TR/2011/WD-touch-events-20110505/#the-touchend-event
  if (!changedTouch) {
    return;
  }
  var touchTarget = document.elementFromPoint(changedTouch.clientX, changedTouch.clientY);
  if (touchTarget && touchTarget !== event.target) {
    fix(touchTarget);
  }
});

Codepen Demo

jimon
sumber
0

Anda bisa coba cara ini.

javascript:

var isEventSupported = function (eventName, elementName) {
    var el = elementName ? document.createElement(elementName) : window;
    eventName = 'on' + eventName;
    var isSupported = (eventName in el);
    if (!isSupported && el.setAttribute) {
        el.setAttribute(eventName, 'return;');
        isSupported = typeof el[eventName] == 'function';
    }
    el = null;
    return isSupported;
};

if (!isEventSupported('touchstart')) {
    $('a').addClass('with-hover');
}

css:

a.with-hover:hover {
  color: #fafafa;
}
Lorenzo Polidori
sumber
0

Apa yang saya lakukan sejauh ini dalam proyek-proyek saya adalah mengembalikan :hoverperubahan pada perangkat sentuh:

.myhoveredclass {
    background-color:green;
}
.myhoveredclass:hover {
    background-color:red;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
    .myhoveredclass:hover, .myhoveredclass:active, .myhoveredclass:focus {
        background-color:green;
    }
}

Semua nama kelas dan nama warna hanya untuk tujuan demonstrasi ;-)

z00l
sumber
0

Ini berfungsi sempurna dalam 2 langkah.

  1. Atur tag tubuh Anda menjadi seperti ini <body ontouchstart="">. Saya bukan penggemar "peretasan" ini, tetapi memungkinkan Safari di iOS bereaksi terhadap sentuhan secara instan. Tidak yakin bagaimana, tetapi itu berhasil.

  2. Atur kelas terjamah Anda seperti ini:

    // I did this in SASS, but this should work with normal CSS as well
    
    // Touchable class
    .example {
    
        // Default styles
        background: green;
    
        // Default hover styles 
        // (Think of this as Desktop and larger)
        &:hover {
            background: yellow;
        }
    
        // Default active styles
        &:active {
            background: red;
        }
    
        // Setup breakpoint for smaller device widths
        @media only screen and (max-width: 1048px) {
    
            // Important!
            // Reset touchable hover styles
            // You may want to use the same exact styles as the Default styles
            &:hover {
                background: green;
            }
    
            // Important!
            // Touchable active styles
            &:active {
                background: red;
            }
        }
    }

Anda mungkin ingin menghapus animasi apa pun di kelas yang dapat Anda sentuh. Android Chrome tampaknya sedikit lebih lambat dari iOS.

Ini juga akan menghasilkan status aktif yang diterapkan jika pengguna menggulir halaman saat menyentuh kelas Anda.

Michael
sumber
0

Beberapa masalah lengket atau macet :hover :focus :activepada perangkat seluler mungkin disebabkan oleh hilangnya <meta name="viewport" content="width=device-width">karena peramban mencoba memanipulasi layar.

GEkk
sumber
0

Solusi bagi saya adalah setelah touchend adalah untuk mengkloning dan mengganti node ... Aku benci melakukan ini tetapi bahkan mencoba mengecat ulang elemen dengan offsetHeight tidak bekerja

    let cloneNode = originNode.cloneNode( true );
    originNode.parentNode.replaceChild( cloneNode, originNode );
Larangan
sumber
Pada akhirnya ini tidak berhasil untuk saya ... kasus saya, saya harus mengkloning seluruh ES6 yang diperpanjang dan beberapa pendengar acara dan itu mulai menjadi rumit untuk menyelesaikan hal sekecil itu.
Larangan
0

Ini dapat dilakukan dengan menukar kelas HTML. Seharusnya lebih rentan terhadap gangguan daripada menghapus seluruh elemen, terutama dengan tautan gambar besar, dll.

Kita juga dapat memutuskan apakah kita ingin melayang status dipicu saat menggulir dengan sentuhan (touchmove) atau bahkan menambahkan batas waktu untuk menunda mereka.

Satu-satunya perubahan signifikan dalam kode kami akan menggunakan kelas HTML tambahan seperti <a class='hover'></a>pada elemen yang menerapkan perilaku baru.

HTML

<a class='my-link hover' href='#'>
    Test
</a>

CSS

.my-link:active, // :active can be turned off to disable hover state on 'touchmove'
.my-link.hover:hover {

    border: 2px dotted grey;
}

JS (dengan jQuery)

$('.hover').bind('touchstart', function () {

   var $el;
   $el = $(this);
   $el.removeClass('hover'); 

   $el.hover(null, function () {
      $el.addClass('hover');
   });
});

Contoh

https://codepen.io/mattrcouk/pen/VweajZv

-

Saya tidak memiliki perangkat dengan mouse dan sentuh untuk mengujinya dengan benar.

Maciek Rek
sumber
0

Dari 2020 Anda dapat menambahkan gaya hover di dalam kueri media

@media (hover: hover) and (pointer: fine) {
    /* css hover class/style */
}

Kueri media ini menunjukkan bahwa gaya akan berfungsi pada peramban yang tidak meniru: arahkan kursor sehingga TIDAK akan berfungsi pada peramban sentuh.

Dawid Świtoń
sumber