Dokunmatik cihazlardaki düğmeler için yapışkan vurgulu efektler nasıl önlenir


144

Her zaman görünür olan bir önceki ve bir sonraki düğmeyle bir atlıkarınca oluşturdum. Bu düğmelerin üzerinde durma durumu vardır, maviye döner. İPad gibi dokunmatik cihazlarda fareyle üzerine gelme durumu yapışkandır, bu nedenle dokunduktan sonra düğme mavi kalır. Bunu istemiyorum.

  • Her düğme için bir no-hoversınıf ekleyebilir ontouchendve CSS'imi böyle yapabilirim: button:not(.no-hover):hover { background-color: blue; }ancak bu muhtemelen performans için oldukça kötü ve Chromebook Pixel (hem dokunmatik ekrana hem de fareye sahip) gibi cihazları doğru şekilde işlemiyor.

  • Bir touchsınıf ekleyebilir documentElementve CSS'imi şu şekilde yapabilirim: html:not(.touch) button:hover { background-color: blue; }Ama bu hem dokunma hem de fare ile cihazlarda doğru çalışmıyor.

Tercih ettiğim şey fareyle üzerine gelme durumunu kaldırmak ontouchend. Ancak bu mümkün görünmüyor. Başka bir öğeye odaklanmak fareyle üzerine gelme durumunu kaldırmaz. Başka bir öğeye manuel olarak hafifçe vurmak işe yarar, ancak bunu JavaScript'te tetikleyemiyorum.

Bulduğum tüm çözümler kusurlu görünüyor. Mükemmel bir çözüm var mı?

Yanıtlar:


55

Bağlantıyı DOM'dan geçici olarak kaldırarak fareyle üzerine gelme durumunu kaldırabilirsiniz. Bkz. Http://testbug.handcraft.com/ipad.html


CSS'de:

:hover {background:red;}

JS'de:

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

Ve sonra HTML'nizde:

<a href="#" ontouchend="this.onclick=fix">test</a>

3
@Chris İyi bir nokta, ontouchend olayında onclick işleyicisini ayarlamak için örneği değiştirdim.
Sjoerd Visscher

4
Lütfen yanıtınıza en az açıklayıcı kod eklemeyi düşünün. Teşekkürler! stackoverflow.com/help/how-to-answer
2540625 16:14

1
@SjoerdVisscher Yapıştırdım. StackOverflow, bağlantılar gidebileceğinden kodun yanıtta olmasını ister. (Ve bu durumda sadece tıklamak değil, aynı zamanda kaynağı görüntülemek ve hangi bitlerin söz konusu teknik olduğunu bulmak da gerekiyordu.)
Darren Cook

2
@KevinBorders evet bazı cihazlarda elemanın çıkarılması ve tekrar takılması arasındaki zaman gecikmesi çok dikkat çekici olabilir. Ne yazık ki, android 4.4 cihazımda setTimeout olmadan bunu yapmadığını buldum.
Rodney

1
Fikir ilginç, ama biraz sarsıntılı buldum ve tüm dokunmatik cihazlarda yaygın olarak desteklenmedi. Bu gibi dokunmatik destek algılama ve saf css dayalı daha az invaziv bir çözüm tercih ediyorum stackoverflow.com/a/39787268/885464
Lorenzo Polidori

83

Bir kez CSS Medya Sorguları Seviye 4 uygulanmaktadır, bunu yapmak mümkün olacak:

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

Veya İngilizce: "Tarayıcı uygun / doğru / gerçek / taklitsiz gezinmeyi destekliyorsa (örneğin, fare benzeri bir birincil giriş aygıtı varsa), üzerine geldiğinde bu stili uygulayın button."

Medya Sorguları Düzey 4'ün bu kısmı şimdiye kadar yalnızca kanayan Chrome'da uygulandığından, bununla başa çıkmak için bir çoklu dolgu yazdım . Bunu kullanarak, yukarıdaki fütüristik CSS'yi şuna dönüştürebilirsiniz:

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

( .no-touchTekniğin bir varyasyonu ) Ve ardından fareyle üzerine gelme desteğini algılayan aynı çoklu dolgudaki bazı istemci tarafı JavaScript'i kullanarak, my-true-hoversınıfın varlığını buna göre değiştirebilirsiniz:

$(document).on('mq4hsChange', function (e) {
    $(document.documentElement).toggleClass('my-true-hover', e.trueHover);
});

Teşekkürler! Benim amacım için bu çoğu tarayıcı caniuse.com/#search=media%20queries desteklenmiş gibi görünüyor ve mükemmel çalışıyor, teşekkürler!
ragamufin

3
Bunun yerine caniuse.com/#feat=css-media-interaction'a bakmanız gerekiyor ve bunun Firefox ve IE11'de desteklenmediğini göreceksiniz :( yani çoklu doldurmaya ihtiyacınız var
CherryDT

Görünüşe göre
çoklu dolgu

Bu, artık mobil tarayıcılarda yaygın olarak destekleniyor ve cazibe gibi çalışıyor. Bence kabul edilen cevap olmalı.
Trevor Burnham

Bu kesinlikle uygulanması en kolay ve en iyi cevaptır. Android Mobile ve PC'de Firefox'ta çalışır. Çift dokunma ve fare aygıtlarından emin değilim.
HalfMens

28

Bu, mükemmel bir çözümü olmayan yaygın bir sorundur. Fareyle üzerine gelme davranışı fare ile yararlıdır ve çoğunlukla dokunma ile zararlıdır. Sorunu birleştirmek, Chromebook Pixel ve Surface gibi dokunma ve fareyi (aynı anda, daha az değil!) Destekleyen cihazlardır.

Bulduğum en temiz çözüm, fareyle üzerine gelme davranışını yalnızca cihazın dokunmatik girişi desteklemediği düşünülüyorsa etkinleştirmektir.

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

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

Kabul ederseniz, fareyi destekleyebilecek cihazlarda imleci kaybedersiniz. Bununla birlikte, bazen fareyle üzerine gelindiğinde bağlantının kendisinden daha fazla etkilenir; örneğin, bir öğe üzerine geldiğinde bir menü göstermek isteyebilirsiniz. Bu yaklaşım, dokunmanın varlığını test etmenize ve belki de şartlı olarak farklı bir olay eklemenize izin verir.

Bunu iPhone, iPad, Chromebook Pixel, Surface ve çeşitli Android cihazlarda test ettim. Karışıma genel bir USB dokunmatik giriş (ekran kalemi gibi) eklendiğinde çalışacağını garanti edemiyorum.


1
Harika, bu benim için çalıştı, topluluk wiki / Darren Cook cevap aksine.
Jannik

1
İyi cevap. Bu benzer bir çözümdür: stackoverflow.com/a/39787268/885464
Lorenzo Polidori

11

Modernizr ile fareyle üzerine gelindiğinde özellikle dokunmasız cihazlar için hedefleme yapabilirsiniz:

(Not: Bu, StackOverflow'un snippet sisteminde çalışmaz, bunun yerine jsfiddle'ı kontrol edin )

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

Hem mobil hem de masaüstünde beklendiği gibi çalıştığı :activeiçin hedeflenmesi gerekmediğini unutmayın .no-touch.


Bu en iyi cevap IMO AMA örnek yanlış. Dokunmatik ve dokunmatik olmayan cihazlar için aynı fareyle üzerine gelme durumunu gösterir. Bu, yalnızca vurgulu devlet uygulamalıdır .no-touchbulunduğundan htmletiketi. Aksi takdirde, bu cevap onay damgamı alır.
morrisbret

2
Sorun şu ki, dokunmatik ekranlı fare özellikli cihazlar artık her yerde, artık bu yönteme artık güvenemiyorsunuz. Ancak bunu yapmak için başka bir yol çok göremiyorum ... bu oldukça bir ikilem
dudewad

Bunu yapmanın bir yolunun hem Modernizr'i hem de mobile-detect.js gibi bir kitaplığı kullanmak olduğunu düşünüyorum.
Gavin

Kurtarıcısınız, bu mobil cihazlar için mükemmel çalıştı çok teşekkürler
Shivam

9

Fareyle üzerine gelme özelliğini desteklemeyen cihazlar için fareyle üzerine gelme efektini geçersiz kılabilirsiniz. Sevmek:

.my-thing {
    color: #BADA55;
}

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

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

İOS 12'de test edildi ve doğrulandı

Bunu işaret etmek için https://stackoverflow.com/a/50285058/178959 adresine şapka ipucu .


Bu daha modern bir çözümdür, javascript veya DOM manipülasyona gerek yoktur, tam tarayıcı desteğine sahiptir (IE hariç) ve kabul edilen cevap olmalıdır.
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();
});

Bu yanıtı, click () yerine on () kullanarak iyileştirebilirsiniz. Öğeyi DOM'dan kaldırarak ve yeniden ekleyerek tıklama etkinliklerimi kaybettim. Fonksiyonumu on ile yeniden yazdığımda, öğeye bağlama, sonra kaldırma ve ekleme çalıştı. Örneğin: `` $ ('body'). On ('click', '# elementwithhover', function () {// clone, insertafter, remove}); Eğer bu değişikliği yaparsanız, oylayacağım.
16:16

true klonu, öğenin sıkışmış vurgulu yerini alarak yeni öğe üzerinde tıklama olayını korur. orijinal eleman klonlandıktan sonra domdan çıkarılır.
Verard Sloggett

harika kardeşim, 10x
Kaloyan Stamatov

Saatlerce bir düzeltme arayışı ve nihayet bir çözüm sağladı. Milyonlarca kez teşekkürler!
phil917

8

Gönderen mobil yapışkan üzerine gelindiğinde anlaşma 4 yolları : Burada dinamik eklemek veya "kaldırmak için bir yoldur can touchkullanıcının mevcut giriş türüne göre belgeye" sınıfı. Kullanıcının dokunma ve fare / izleme dörtgeni arasında geçiş yapabileceği hibrit cihazlarla da çalışır:

<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>

Bu bulduğum en iyi yol, artı zamanlayıcıyı 1000 ms'ye çıkarırsanız, uzun basmayı da kaplayabilirsiniz, buraya bakın . Harika şeyler!
lowtechsun

3

Kendi çözümümü gönderecektim, ama birisinin zaten gönderip göndermediğini kontrol ederek, @Rodney'nin neredeyse yaptığını gördüm. Ancak, en azından benim durumumda, uniseful hale getiren son bir kritik noktayı kaçırdı. Ben de aynı sürdü, demek .fakeHoveraracılığıyla kaldırarak / sınıf eklenmesini mouseenterve mouseleaveolay algılama, ama bu tek başına, kendi başına , "hakiki" gibi neredeyse tam davranır :hover. Demek istediğim, tablonuzdaki bir öğeye dokunduğunuzda, onu "bıraktığınızı" algılamaz - böylece "sahte" durumu korur.

Yaptığım sadece dinlemek clickde oldu, bu yüzden düğmeye "dokunduğumda" manuel olarak a mouseleave.

Si bu benim son kod:

.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();
});

Bu şekilde hover, düğmelerinizde "fareyle gezindiğinizde" fareyi kullanırken olağan işlevselliğinizi korursunuz. Neredeyse hepsi: bir şekilde tek dezavantajı, fare ile düğmeye tıkladıktan sonra hoverdurum olmayacak . Tıpkı işaretçiyi tıklayıp hızlı bir şekilde düğmeden çıkardığınızda olduğu gibi. Ama benim durumumda bununla yaşayabilirim.


2

Geri kalan cevapları inceledikten sonra şimdiye kadar bulduğum şey bu. Yalnızca dokunma, yalnızca fare veya karma kullanıcıları destekleyebilmelidir.

Fareyle üzerine gelme efekti için ayrı bir fareyle üzerine gelme sınıfı oluşturun. Varsayılan olarak, bu fareyle üzerine gelme sınıfını düğmemize ekleyin.

Dokunmatik desteğin varlığını tespit etmek ve tüm fareyle üzerine gelme efektlerini en başından devre dışı bırakmak istemiyoruz. Başkaları tarafından belirtildiği gibi, hibrid cihazlar popülerlik kazanıyor; insanlar dokunma desteğine sahip olabilirler, ancak fare kullanmak isterler ya da tam tersi. Bu nedenle, fareyle üzerine gelme sınıfını yalnızca kullanıcı düğmeye gerçekten dokunduğunda kaldırın.

Bir sonraki sorun, kullanıcı düğmeye dokunduktan sonra fare kullanmaya geri dönmek isterse ne olur? Bunu çözmek için, kaldırdığımız vurgulu sınıfı geri eklemek için fırsatlı bir an bulmamız gerekiyor.

Ancak, fareyle üzerine gelme durumu hala etkin olduğundan, kaldırdıktan hemen sonra geri ekleyemeyiz. Düğmenin tamamını da yok etmek ve yeniden oluşturmak istemeyebiliriz.

Bu yüzden, fareyle üzerine gelme durumunu kontrol etmek için meşgul bekleyen bir algoritma (setInterval kullanarak) kullanmayı düşündüm. Fareyle üzerine gelme durumu devre dışı bırakıldıktan sonra, fareyle üzerine gelme sınıfını geri ekleyebilir ve meşgul beklemeyi durdurabilir, böylece kullanıcı fareyi veya dokunmayı kullanabileceği orijinal duruma geri getirebiliriz.

Meşgul beklemenin o kadar da iyi olmadığını biliyorum ama uygun bir etkinlik olup olmadığından emin değilim. Mouseleave etkinliğine geri eklemeyi düşündüm, ancak çok sağlam değildi. Örneğin, düğmeye dokunduktan sonra bir uyarı çıktığında, fare konumu değişir, ancak fareyle açılan olay tetiklenmez.

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>

Düzenleme: Ben denedim başka bir yaklaşım e.preventDefault()ontouchstart veya ontouchend içinde aramaktır. Düğmeye dokunulduğunda fareyle üzerine gelme efektini durdurduğu görülüyor, ancak düğme tıklama animasyonunu da durduruyor ve düğmeye dokunulduğunda onclick işlevinin çağrılmasını önlüyor, bu yüzden bunları başaşağı veya alt işleyicide manuel olarak çağırmanız gerekiyor. Çok temiz bir çözüm değil.


1

Benim için yararlı oldu: link

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");
                    }
                }
            }
        }
    }
}

Genel ontouchstart olay işleyicisinden hoverTouchUnstick () öğesini bir kez çağırmanız gerekir. Ve bu çözüm mükemmel çalışır.
18'de Jusid

1

Bu JS kodunu sayfanıza ekleyin:

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

şimdi her fareyle gezinme işleminden önce CSS'nize ekleyin:

.hover .foo:hover {}

Eğer cihaza dokunulursa, vücut sınıfı boş olacaktır, aksi takdirde sınıfının üzerine gelinecek ve kurallar uygulanacaktır!


Benim için çalışmadı, ama bu işe yaradı:document.body.className = 'ontouchstart' in window ? '' : 'hover';
drskullster

1

Her düğme için üzerine dokunmayan bir sınıf ekleyebilir ve CSS'imi> bu gibi yapabilirim: düğme: değil (.no-hover): hover {background-color: blue; } ancak bu muhtemelen performans açısından oldukça kötüdür ve Chromebook Pixel (hem dokunmatik ekrana hem de fareye sahip) gibi cihazları doğru şekilde işlemez.

Bu doğru başlangıç ​​noktası. Sonraki adım: Aşağıdaki etkinliklerde nohover sınıfını uygulama / kaldırma (jQuery ile demo)

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

Uyarı: Düğme sınıfına başka sınıflar uygulamak isterseniz, CSS'deki: not (.nohover) artık beklendiği gibi çalışmaz. Daha ziyade fareyle üzerine gelindiğinde stilin üzerine yazmak için varsayılan değer ve! Önemli etiketi olan ayrı bir tanım eklemeniz gerekir: .nohover {background-color: white! İmportant}

Bu, Chromebook Pixel (hem dokunmatik ekrana hem de fareye sahip) gibi cihazları doğru bir şekilde işlemelidir! Ve bunun büyük bir performans katili olduğunu sanmıyorum ...


1

Benim için çalışan bir çözüm:

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

Bu kodu stil sayfanıza ekleyin.

Bir bağlantı tıklandığında iOS Safari'de görünen gri arka plandan kurtulmak istedim. Ama daha fazlasını yapıyor gibi görünüyor. Şimdi bir düğmeye tıklamak (bir :hoversahte cam ile!) Hemen açılır! Sadece bir iPad'de test ettim, diğer cihazlarda çalışıp çalışmayacağını bilmiyorum.


1

Ben benzer bir sorun için zarif (minimum js) bir çözüm buldum düşünüyorum:

JQuery kullanarak, fareyle (veya başka bir öğeyle) fareyle üzerine gelip .mouseover()

Bu yüzden elemanın ontouchendolayına şöyle bir işleyici ekliyorum :

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

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

Bununla birlikte, bu yalnızca kaldırır: kaydırma veya başka bir dokunma gibi başka bir dokunma olayı tetiklendikten sonra imlecin psödoklasını öğeden tutun


1
Kod snippet'iniz için, dokunduktan sonra kare hala pembe kalıyor. Sanırım bu soruda sorulan sorunu gerçekten çözmediniz mi?
Kevin Lee

Bu çözüm işe yaramıyor. İlk olarak, bir olayı çağırmak için yanlış yöntemi kullandınız, .trigger () kullanmalısınız . İkincisi, mobil safaride hiçbir şekilde çalışmaz.
xHocquet

1

Paylaşmak istediğim güzel bir çözümüm var. Öncelikle, kullanıcının bu şekilde mobilde olup olmadığını tespit etmeniz gerekir:

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

Sonra ekleyin:

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

Ve CSS'de:

.navbar-ul.hoverable li a:hover {
    color: #fff;
}

2
Windows dokunmatik ekranlı PC'ler gibi karma cihazlarda çalışmaz.
cspolton

1

Benzer sorunu yaşadım, uygulamam tüm ekran boyutları için uyumluydu, masaüstü ekran boyutunda / fare tabanlı cihazlarda çok fazla hover etkisi vardı ve daha sonra dokunmatik tabanlı cihazların yapışkan olarak bilinen bir duruma neden olduğunu fark ettim - asılı ve uygulamanın dokunmatik tabanlı cihaz kullanıcıları için düzgün çalışması bir engeldi.

Bizim app SCSS kullanıyorduk . ve dokunmaya dayalı cihaza bakmak için bir mixin tanımladım .

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

ve sonra tüm css derslerimi aşağıda belirtilen snippet'in altına yerleştirdim.

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

Örneğin, bir simgeyi canlandırmak için bir sınıfımız vardı ve simgeyi css'den görebildiğiniz gibi üzerine getirdikten sonra tetikleyen bir sınıfımız vardı, ancak dokunmatik tabanlı cihazda yapışkan vurgulu efektten etkileniyordu ve sonra @ içine yerleştirdim fareyle üzerine gelme işlevinin yalnızca fareyle üzerine geleni destekleyen cihazlara uygulanmasını sağlamak için fareyle üzerine gelme desteği () ekleyin .

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

1

İşte geliştiricinin CSS'yi düzenlemesini veya yeni CSS kuralları yazmasını gerektirmeyen basit bir JavaScript kodu. Bunu Bootstrap düğmeleri için yazdım class="btn", ancak belirli bir sınıf adına sahip herhangi bir düğme ile çalışacaktır.

Adımlar:

  1. bunun bir dokunmatik cihaz olup olmadığını belirleme
  2. öyleyse, içindeki her CSS kuralını yineleyin document.styleSheets
  3. her ikisini de içeren herhangi bir kuralı sil .btnve:hover

Tüm .btn :hoverCSS kurallarının kaldırılması , bir düğme üzerinde görsel fareyle üzerine gelme etkisi olmayacağını garanti eder.

Adım 1: Dokunmatik Cihazı Algıla

Ortam sorgusunun varlığını kontrol edin (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;
    };

Adım 2: `btn` ve`: hover` İçeren CSS Kurallarını Silin

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

Kodun tamamı GitHub ve npm'de .

Terrymorse.com adresinden canlı demo .


Bu, fare / izleme dörtgeni olan dokunmatik ekranlı cihazlar için fareyle üzerine gelme efektini de kaldırmıyor mu?
Jensei

@Jensei Muhtemelen. Aygıt eşleşirse @media (hover:none)veya kullanıcı ekrana ilk kez dokunduğunda fareyle üzerine gelme kuralları kaldırılır . Emin olmak için canlı demo sayfasında deneyebilirsiniz.
terrymorse

0

Arka plan rengini :activedurumuna ayarlayabilir ve :focus varsayılan arka planı verebilirsiniz .

üzerinden arka plan rengi ayarlarsanız onfocus/ontouch, :focusdurum geçtikten sonra renk stili kalır . Odak kaybolduğunda varsayılan bg'yi geri yüklemek için de
sıfırlamanız gerekir onblur.


Ancak fare kullanıcıları için fareyle üzerine gelme efektini korumak istiyorum.
Chris

: vurgulu ve: aktif aynı CSS alabilir, açık: odak sorun var. Aslında, netleme yoluyla arka plan rengini ayarlarsanız, netleme bittiğinde renk stili kalır. varsayılan ayar bg'yi geri yüklemek için onlur üzerinde de bir sıfırlamaya ihtiyacınız var
G-Cyrillus

0

Bu benim için çalıştı: vurgulu stili yeni bir sınıfa koy

.fakehover {background: red}

Ardından gerektiğinde sınıfı ekleyin / kaldırın

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

Dokunmatik başlangıç ​​ve dokunmatik uç etkinlikleri için tekrarlayın. Veya istediğiniz sonucu elde etmek için hangi olayları isterseniz, örneğin fareyle üzerine gelme efektinin dokunmatik ekranda açılmasını istedim.


0

Darren Cooks yanıtına dayanarak, parmağınızı başka bir öğenin üzerine getirdiğinizde de işe yarar.

Bkz. Touchend etkinliği sırasında öğe parmağını bulma açık

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


0

Bu şekilde deneyebilirsiniz.

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

0

Projelerimde şimdiye kadar yaptığım şey, :hoverdokunmatik cihazlardaki değişiklikleri geri almaktı :

.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;
    }
}

Tüm sınıf adları ve adlandırılmış renkler sadece tanıtım amaçlıdır ;-)


0

Bu 2 adımda mükemmel çalışır.

  1. Gövde etiketinizi böyle olacak şekilde ayarlayın <body ontouchstart="">. Bu "hack" hayranı değilim, ancak iOS'ta Safari'nin dokunuşlara anında tepki vermesine izin veriyor. Nasıl olduğundan emin değilim, ama işe yarıyor.

  2. Dokunulabilir sınıfınızı şu şekilde ayarlayın:

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

Dokunmatik sınıfınızdaki animasyonları da kaldırmak isteyebilirsiniz. Android Chrome, iOS'tan biraz daha yavaş görünüyor.

Bu, kullanıcı sınıfınıza dokunurken sayfayı kaydırırsa etkin durumun uygulanmasına da neden olur.


0

:hover :focus :activeMobil cihazlar üzerindeki bazı yapışkan veya sıkışmış sorunların nedeni <meta name="viewport" content="width=device-width">, tarayıcılar ekranı değiştirmeye çalışırken eksik olabilir .


0

Benim için çözüm, touchend'in düğümü klonlamak ve değiştirmek oldu ... Bunu yapmaktan nefret ediyorum, ancak bile ofset ile öğeyi yeniden boyamaya çalışıyorum

    let cloneNode = originNode.cloneNode( true );
    originNode.parentNode.replaceChild( cloneNode, originNode );

Sonunda bu benim için işe yaramadı ... Benim durumumda, genişletilmiş bir ES6'nın tamamını ve birkaç olay dinleyicisini klonlamak zorunda kalacağım ve böyle küçük bir şeyi çözmek için karmaşıklaşmaya başladı.
Banning

0

Bir HTML sınıfını değiştirerek başarılabilir. Özellikle büyük, resim bağlantıları vb. İle tüm öğeyi kaldırmaktan daha az aksaklıklara sahip olmalıdır.

Ayrıca , dokunarak (touchmove) kaydırırken fareyle üzerine gelme durumlarının tetiklenmesini isteyip istemediğimize karar verebiliriz veya hatta geciktirmek için bir zaman aşımı ekleyebiliriz.

Kodumuzdaki tek önemli değişiklik <a class='hover'></a>, yeni davranışı uygulayan öğeler gibi ek HTML sınıfı kullanmak olacaktır .

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 (jQuery ile)

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

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

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

Misal

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

-

Yine de düzgün bir şekilde test etmek için hem fare hem de dokunma özellikli bir cihazım yok.


0

2020'den itibaren Ortam sorgusuna fareyle üzerine gelme stilleri ekleyebilirsiniz

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

Bu medya sorgusu, stillerin taklit edilmeyen tarayıcılarda çalışacağını gösterir: üzerine gelindiğinde dokunmatik tarayıcılarda çalışmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.