Desativar efeitos de foco em navegadores móveis

113

Estou escrevendo um site que deve ser usado em desktops e tablets. Quando ele está sendo visitado a partir de um desktop, quero que as áreas clicáveis ​​da tela se iluminem com:hover efeitos (cor de fundo diferente, etc.) Com um tablet, não há mouse, então não quero nenhum efeito de foco.

O problema é que, quando toco em algo no tablet, o navegador evidentemente tem algum tipo de "cursor invisível do mouse" que se move para o local onde toquei e o deixa lá - então o que acabei de tocar acende-se com um efeito de foco até que eu toque em outra coisa.

Como posso obter os efeitos de foco quando estou usando o mouse, mas suprimi-los quando estou usando a tela sensível ao toque?

Caso alguém esteja pensando em sugerir isso, não quero usar a detecção de user agent. O mesmo dispositivo pode ter uma tela sensível ao toque e um mouse (talvez não tão comum hoje, mas muito mais no futuro). Não estou interessado no dispositivo, estou interessado em como ele está sendo usado atualmente: mouse ou touchscreen.

Eu já tentei ligar os touchstart, touchmove, e touchendeventos e chamando preventDefault()em todos eles, o que faz suprimir o "cursor do mouse invisível" por algum tempo; mas se eu tocar rapidamente para frente e para trás entre dois elementos diferentes, depois de alguns toques, ele começará a mover o "cursor do mouse" e acender os efeitos de foco de qualquer maneira - é como se o meu preventDefaultnem sempre fosse respeitado. Não vou aborrecê-lo com os detalhes, a menos que seja necessário - nem tenho certeza se essa é a abordagem certa a se tomar; se alguém tem uma solução mais simples, sou todo ouvidos.


Editar: isso pode ser reproduzido com CSS padrão do bog :hover, mas aqui está uma reprodução rápida para referência.

<style>
  .box { border: 1px solid black; width: 150px; height: 150px; }
  .box:hover { background: blue; }
</style>
<div class="box"></div>
<div class="box"></div>

Se você passar o mouse sobre qualquer uma das caixas, terá um fundo azul, o que eu desejo. Mas se você tocar em qualquer uma das caixas, também obterá um fundo azul, que é o que estou tentando evitar.

Eu também postei um exemplo aqui que faz o acima e também engancha os eventos de mouse do jQuery. Você pode usá-lo para ver que a TAP eventos também irá disparar mouseenter, mousemovee mouseleave.

Joe White
fonte
7
@Blender, você leu a pergunta? Já expliquei por que farejar o user agent é uma escolha ruim.
Joe White
Ei Joe, você encontrou alguma solução para isso?
Ismatjon 02 de
Eu estava procurando por esse tipo de pergunta, feliz por ter encontrado!
agpt
Veja também esta pergunta, que trata da desativação do foco em qualquer dispositivo habilitado para toque, não apenas móvel: stackoverflow.com/questions/23885255/…
blade

Respostas:

83

Deduzo da sua pergunta que o efeito de foco muda o conteúdo da sua página. Nesse caso, meu conselho é:

  • Adicione efeitos de foco em touchstarte mouseenter.
  • Remover pairar efeitos sobre mouseleave, touchmovee click.

Como alternativa, você pode editar sua página para que não haja alteração de conteúdo.

fundo

Para simular um mouse, navegadores como o Webkit mobile disparam os seguintes eventos se um usuário tocar e soltar um dedo na tela de toque (como o iPad) (fonte: Touch And Mouse em html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. Atraso de 300 ms, em que o navegador garante que seja um toque único, não um toque duplo
  5. mouseover
  6. mouseenter
    • Nota : Se um mouseover, mouseenterou mousemoveevento muda o conteúdo da página, os seguintes eventos não são disparados.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

Não parece possível simplesmente dizer ao navegador da web para pular os eventos do mouse.

O que é pior, se um evento de mouseover altera o conteúdo da página, o evento de clique nunca é disparado, conforme explicado no Safari Web Content Guide - Handling Events , em particular a figura 6.4 em One-Finger Events . O que exatamente é uma "mudança de conteúdo" dependerá do navegador e da versão. Descobri que para iOS 7.0, uma mudança na cor de fundo não é (ou não é mais?) Uma mudança de conteúdo.

Solução Explicada

Para recapitular:

  • Adicione efeitos de foco em touchstarte mouseenter.
  • Remover pairar efeitos sobre mouseleave, touchmovee click.

Observe que não há nenhuma ação em touchend!

Isso funciona claramente para eventos de mouse: mouseentere mouseleave(versões ligeiramente melhoradas de mouseoveremouseout ) são disparados e adicionam e removem o foco.

Se o usuário realmente for clickum link, o efeito de foco também será removido. Isso garante que ele seja removido se o usuário pressionar o botão Voltar no navegador da web.

Isso também funciona para eventos de toque: na inicialização do toque, o efeito de foco é adicionado. É '' 'não' '' removido no touchend. Ele é adicionado novamente mouseenter, e como isso não causa alterações no conteúdo (ele já foi adicionado), o clickevento também é disparado e o link é seguido sem a necessidade de o usuário clicar novamente!

O atraso de 300 ms que um navegador tem entre um touchstartevento e clické realmente bem utilizado porque o efeito de foco será mostrado durante esse curto período.

Se o usuário decidir cancelar o clique, um movimento do dedo fará isso normalmente. Normalmente, isso é um problema, pois nenhum mouseleaveevento é disparado e o efeito de foco permanece no lugar. Felizmente, isso pode ser facilmente corrigido removendo o efeito de foco em touchmove.

É isso aí!

Observe que é possível remover o atraso de 300ms, por exemplo, usando a biblioteca FastClick , mas isso está fora do escopo desta questão.

Soluções alternativas

Encontrei os seguintes problemas com as seguintes alternativas:

  • detecção do navegador: extremamente sujeito a erros. Presume que um dispositivo tem mouse ou toque, enquanto uma combinação de ambos se tornará cada vez mais comum quando as telas de toque se proliferam.
  • Detecção de mídia CSS: a única solução exclusiva de CSS que conheço. Ainda sujeito a erros e ainda assume que um dispositivo possui mouse ou toque, embora ambos sejam possíveis.
  • Emular o evento de clique em touchend: Isso seguirá o link incorretamente, mesmo que o usuário queira apenas rolar ou aplicar zoom, sem a intenção de clicar no link.
  • Use uma variável para suprimir os eventos do mouse: Isso define uma variável touchendque é usada como uma condição se em eventos subsequentes do mouse para evitar mudanças de estado naquele ponto no tempo. A variável é redefinida no evento de clique. Veja a resposta de Walter Roman nesta página. Esta é uma solução decente se você realmente não quer um efeito de foco nas interfaces de toque. Infelizmente, isso não funciona se a touchendfor disparado por outro motivo e nenhum evento de clique for disparado (por exemplo, o usuário rolou ou fez zoom) e, subsequentemente, tentar seguir o link com um mouse (ou seja, em um dispositivo com mouse e interface de toque )

Leitura Adicional

MacFreek
fonte
1
Boa resposta. Usei seu violino para começar a criar minha própria solução. O touchend às vezes é necessário. (quando um touchmove não é executado - ou seja, quando o usuário sai do próprio documento ...)
Agamemnus
Ótima resposta, mas na maioria dos casos, eu sugiro usar em touchend vez de touchstartna maioria dos casos, para evitar ações de gatilho imediatamente quando o usuário está tentando rolar para cima ou para baixo em uma página. Ainda acontecerá, mas é menos provável que distraia ou confunda (presumindo que seja algo inofensivo, como exibir um rótulo, não algo que o usuário precise saber que aconteceu)
user56reinstatemonica8
19

Como posso obter os efeitos de foco quando estou usando o mouse, mas suprimi-los quando estou usando a tela sensível ao toque?

Talvez não pense nisso tanto como suprimir efeitos de foco para telas sensíveis ao toque, mas como adicionar efeitos de foco para eventos de mouse?

Se você deseja manter os :hoverefeitos em seu CSS, pode especificar estilos diferentes para mídias diferentes:

@media screen { /* hover styles here */ } 

@media handheld { /* non-hover styles here */ }

Só que infelizmente existem muitos dispositivos móveis que ignoram isso e apenas usam as regras da tela. Felizmente, muitos dos navegadores de celular / tablet mais recentes suportam algumas consultas de mídia mais sofisticadas:

@media screen and (max-width:800px) { /* non-hover styles here */ }

Portanto, mesmo se a parte "tela" ou "dispositivo portátil" for ignorada, a "largura máxima" fará o truque para você. Você pode simplesmente supor que qualquer coisa com uma tela menor que 800 pixels deve ser um tablet ou telefone, e não usar efeitos de foco. Para os raros usuários que estão usando um mouse em um dispositivo de baixa resolução, eles não veriam os efeitos de foco, mas seu site estaria bem de outra forma.

Leituras adicionais sobre consultas de mídia? Existem muitos artigos sobre isso online - aqui está um: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

Se você deslocar os efeitos de foco de seu CSS e aplicá-los com JavaScript, você pode vincular especificamente a eventos de mouse e / ou novamente, você pode apenas fazer algumas suposições apenas com base no tamanho da tela com o "problema" de pior caso sendo que alguns o usuário que usa o mouse perde os efeitos de foco.

nnnnnn
fonte
Adoraria adicionar efeitos de foco apenas para eventos de mouse. Mas os eventos de toque emulam os eventos do mouse. Se eu enganchar os eventos de toque e chamar preventDefault(), isso às vezes suprime os eventos do mouse, mas como eu disse na minha pergunta, não é confiável.
Joe White
6
Quanto às consultas de mídia, o que acontece quando o Windows 8 é lançado e os PCs têm telas sensíveis ao toque e mouses? Se o usuário passar o mouse, eles verão o cursor do mouse e eu quero os efeitos de foco; se eles tocarem com a tela sensível ao toque, não quero os efeitos de foco. Mas não encontrei uma maneira confiável de detectar a diferença entre toque e mouse.
Joe White
Bem, talvez os desenvolvedores de navegadores fiquem mais motivados para tornar a detecção mais consistente, uma vez que tenham um número maior de usuários em dispositivos com toque e mouse. Mas para agora? Eu estaria fazendo suposições com base no tamanho da tela, mas há outros conselhos nas outras respostas. Desculpe, não posso ajudar mais.
nnnnnn
9

Escrevi o seguinte JS para um projeto recente, que era um site para desktop / celular / tablet que tem efeitos de foco que não deveriam aparecer ao toque.

O mobileNoHoverStatemódulo abaixo possui uma variável preventMouseover(declarada inicialmente como false), que é definida para truequando um usuário dispara o touchstartevento em um elemento $target,.

preventMouseoveré então definido de volta para falsesempre que omouseover evento for disparado, o que permite que o site funcione como pretendido se um usuário estiver usando a tela sensível ao toque e o mouse.

Sabemos que mouseoverestá sendo acionado depois touchstartpor causa da ordem em que estão sendo declarados init.

var mobileNoHoverState = function() {

    var hoverClass = 'hover',
        $target = $(".foo"), 
        preventMouseover = false;

    function forTouchstart() {
        preventMouseover = true;
    }

    function forMouseover() {
        if (preventMouseover === false) {
            $(this).addClass(hoverClass);
        } else {
            preventMouseover = false;
        }
    }

    function forMouseout() {
        $(this).removeClass(hoverClass);
    }

    function init() {
        $target.on({
            touchstart  : forTouchstart,
            mouseover   : forMouseover,
            mouseout    : forMouseout
        });                
    }

    return {
        init: init
    };
}();

O módulo é então instanciado mais adiante na linha:

mobileNoHoverState.init();
Walter Roman
fonte
"preventMouseover é então definido de volta para true sempre que o evento mouseover é disparado, o que permite que o site funcione como pretendido se um usuário estiver usando a tela sensível ao toque e o mouse." - Seu código não está fazendo isso. Estou esquecendo de algo?
Redtopia de
@Redtopia Obrigado pelo aviso! Atualizei a resposta com o trecho de código que foi deixado de fora.
Walter Roman,
Você não precisa de ponto-e-vírgula após a declaração da função
nacholibre
@nacholibre O uso adequado de ponto-e-vírgula foi implementado
Walter Roman
6

Eu realmente queria uma csssolução pura para isso, já que espalhar uma solução javascript pesada em todas as minhas visualizações parecia uma opção desagradável. Finalmente encontrei o @ media.hover consulta , que pode detectar "se o mecanismo de entrada principal permite que o usuário passe o mouse sobre os elementos." Isso evita dispositivos de toque onde "pairar" é mais uma ação emulada do que uma capacidade direta do dispositivo de entrada.

Por exemplo, se eu tiver um link:

<a href="/" class="link">Home</a>

Então, posso estilizá-lo com segurança apenas :hoverquando o dispositivo o suportar facilmente com isto css:

@media (hover: hover) {
  .link:hover { /* hover styles */ }
}

Enquanto a maioria dos navegadores modernos oferece suporte a consultas de recursos de mídia de interação, alguns navegadores populares , como o IE e o Firefox , não. No meu caso, isso funciona bem, já que eu pretendia apenas oferecer suporte ao Chrome no desktop e ao Chrome e Safari no celular.

Flintinatux
fonte
Boa solução que parece funcionar quando você emula dispositivos no Chrome Devtools. Mas ainda não funciona para o Chrome Android :-(
Sjeiti 01 de
Acho que esta é a solução mais conveniente e correta. Espero que seja adicionado aos padrões W3C em breve.
GProst
5

Minha solução é adicionar a classe css hover-active à tag HTML e usá-la no início de todos os seletores CSS com: hover e remover essa classe no primeiro evento touchstart.

http://codepen.io/Bnaya/pen/EoJlb

JS:

(function () {
    'use strict';

    if (!('addEventListener' in window)) {
        return;
    }

    var htmlElement = document.querySelector('html');

    function touchStart () {
        document.querySelector('html').classList.remove('hover-active');

        htmlElement.removeEventListener('touchstart', touchStart);
    }

    htmlElement.addEventListener('touchstart', touchStart);
}());

HTML:

<html class="hover-active">

CSS:

.hover-active .mybutton:hover {
    box-shadow: 1px 1px 1px #000;
}
Bnaya
fonte
Em vez de ouvir um evento de toque, você pode testar 'ontouchstart' in window. por exemploif ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Yuval A.
@YuvalA. O motivo pelo qual estou esperando o evento de toque é que existem dispositivos com apontador e suporte para toque, e o usuário está usando o apontador e não quero remover o foco. É possível que o usuário use o toque e o ponteiro, mas não tenho muito o que fazer a respeito
Bnaya
2

O que fiz para resolver o mesmo problema é ter uma detecção de recurso (uso algo como este código ), ver se onTouchMove está definido e, se estiver, adiciono a classe css "touchMode" ao corpo, caso contrário, adiciono " desktopMode ".

Então, toda vez que algum efeito de estilo se aplica apenas a um dispositivo de toque, ou apenas a um desktop, a regra css é anexada com a classe apropriada:

.desktopMode .someClass:hover{ color: red }
.touchMode .mainDiv { width: 100%; margin: 0; /*etc.*/ }

Edit : Esta estratégia, é claro, adiciona alguns caracteres extras ao seu css, então se você estiver preocupado com o tamanho do css, você pode pesquisar as definições touchMode e desktopMode e colocá-los em arquivos diferentes, para que possa servir css otimizado para cada dispositivo tipo; ou você pode alterar os nomes das classes para algo muito mais curto antes de começar.

Stein G. Strindhaug
fonte
2

Certo, eu só tive um problema semelhante, mas consegui corrigi-lo com consultas de mídia e CSS simples. Tenho certeza de que estou quebrando algumas regras aqui, mas está funcionando para mim.

Basicamente, tive que pegar um aplicativo enorme feito por alguém e torná-lo responsivo. Eles usaram jQueryUI e me pediram para não mexer em nenhum de seus jQuery, então eu estava restrito a usar CSS sozinho.

Quando eu pressionava um de seus botões no modo touchscreen, o efeito de foco disparava por um segundo antes que a ação do botão tivesse efeito. Veja como eu consertei.

@media only screen and (max-width:1024px) {

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   
Daft
fonte
2

No meu projeto, resolvemos esse problema usando https://www.npmjs.com/package/postcss-hover-prefix e https://modernizr.com/ Primeiro, pós-processamos os arquivos css de saída com postcss-hover-prefix. Ele adiciona .no-touchpara todas as hoverregras de css .

const fs = require("fs");
const postcss = require("postcss");
const hoverPrfx = require("postcss-hover-prefix");

var css = fs.readFileSync(cssFileName, "utf8").toString();
postcss()
   .use(hoverPrfx("no-touch"))
   .process(css)
   .then((result) => {
      fs.writeFileSync(cssFileName, result);
   });

css

a.text-primary:hover {
  color: #62686d;
}

torna-se

.no-touch a.text-primary:hover {
  color: #62686d;
}

Em tempo de execução Modernizradiciona automaticamente classes css a htmltags como esta

<html class="wpfe-full-height js flexbox flexboxlegacy canvas canvastext webgl 
  no-touch 
  geolocation postmessage websqldatabase indexeddb hashchange
  history draganddrop websockets rgba hsla multiplebgs backgroundsize borderimage
  borderradius boxshadow textshadow opacity cssanimations csscolumns cssgradients
  cssreflections csstransforms csstransforms3d csstransitions fontface
  generatedcontent video audio localstorage sessionstorage webworkers
  applicationcache svg inlinesvg smil svgclippaths websocketsbinary">

Esse pós-processamento de css plus Modernizr desativa o foco para dispositivos de toque e habilita para outros. Na verdade, essa abordagem foi inspirada no Bootstrap 4, como eles resolvem o mesmo problema: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile

Stanislav Berkov
fonte
1

Você pode acionar o mouseLeaveevento sempre que tocar em um elemento da tela sensível ao toque. Aqui está uma solução para todas as <a>tags:

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}
Disse Kholov
fonte
JSHint diz "não crie funções dentro de um loop".
NetOperator Wibby
É um hack. NÃO é um código reutilizável que pode ser considerado uma boa prática. @NetOperatorWibby
Disse Kholov
Bem, não é realmente útil postar código que não pode ser considerado uma boa prática. É como colocar um curativo em um ferimento de faca.
NetOperator Wibby
1

Iv encontrou 2 soluções para o problema, o que implica que você detecte o toque com modernizr ou outra coisa e defina uma classe de toque no elemento html.

Isso é bom, mas não tem muito suporte :

html.touch *:hover {
    all:unset!important;
}

Mas isso tem um suporte muito bom :

html.touch *:hover {
    pointer-events: none !important;
}

Funciona perfeitamente para mim, faz com que todos os efeitos de foco sejam como quando você toca em um botão, ele acende, mas não acaba com erros como o efeito de foco inicial para eventos de mouse.

Detectando o toque em dispositivos sem toque, acho que a modernizr fez o melhor trabalho:

https://github.com/Modernizr/Modernizr/blob/master/feature-detects/touchevents.js

EDITAR

Eu encontrei uma solução melhor e mais simples para este problema

Como determinar se o cliente é um dispositivo de toque

Simon Dragsbæk
fonte
0

Ver seu CSS pode ajudar, pois parece um problema um tanto estranho. Mas de qualquer maneira, se estiver acontecendo e tudo mais estiver certo, você pode tentar mudar o efeito de foco para javascript (você pode usar jquery também). Simplesmente, vincule-se ao evento mouseover ou, melhor ainda, ao evento mouseenter e acenda seu elemento quando o evento for disparado.

Confira o último exemplo aqui: http://api.jquery.com/mouseover/ , você poderia usar algo semelhante para registrar quando o evento for disparado e partir daí!

balach
fonte
Nada de especial sobre o CSS; veja minha edição. E eu já tentei mouseenter; sem dados. Tocar move o "cursor invisível do mouse", então ele dispara mouseentere mousemove(e mouseleavequando você toca em outro lugar).
Joe White
0

Se você gosta de usar JavaScript, pode usar o Modernizr em sua página. Quando a página carrega, um navegador sem tela de toque terá a classe '.no-touch' adicionada à tag html, mas para um navegador com tela de toque, a tag html terá a classe '.touch' adicionada à tag html .

Em seguida, é simplesmente um caso de verificar se a tag html tem a classe no-touch antes de decidir adicionar os ouvintes do mouseenter e da licença do mouse.

if($('html').hasClass('no-touch')){
    $('.box').on("mouseenter", function(event){
            $(this).css('background-color','#0000ff')
    });
    $('.box').on("mouseleave", function(event){
            $(this).css('background-color','')
    });
}

Para um dispositivo com tela sensível ao toque, os eventos não terão ouvintes, portanto, você não terá efeito de foco quando tocar.

Stanz
fonte
Quando isso pode ser feito com css, não use javascript (jquery), é um desperdício de energia do computador
Simon Dragsbæk
1
Mais simples ainda, em seu CSS, você pode definir regras separadas para .touche .no-touch. Reescrever sua resposta em CSS junto com o Modernizer, html.no-touch .box:hover {background-color: "#0000ff"}e não definir nada para html.touch .box:hoverdeve resolver , já que o OP está apenas tentando evitar :hovers móveis .
Walter Roman
0

Em um projeto que fiz recentemente, resolvi esse problema com o recurso de eventos delegados do jQuery. Ele procura por certos elementos usando um seletor jQuery e adiciona / remove uma classe CSS para esses elementos quando o mouse está sobre o elemento. Parece funcionar bem, tanto quanto fui capaz de testá-lo, que inclui o IE10 em um notebook com capacidade de toque executando o Windows 8.

$(document).ready(
    function()
    {
        // insert your own selector here: maybe '.hoverable'?
        var selector = 'button, .hotspot';

        $('body')
            .on('mouseover', selector, function(){ $(this).addClass('mouseover');    })
            .on('mouseout',  selector, function(){ $(this).removeClass('mouseover'); })
            .on('click',     selector, function(){ $(this).removeClass('mouseover'); });
    }
);

editar: esta solução, é claro, requer que você altere seu CSS para remover os seletores ": hover" e contemple com antecedência quais elementos você deseja que sejam "pairáveis".

Se você tiver muitos elementos em sua página (como vários milhares), pode ficar um pouco lento, porque essa solução captura eventos de três tipos em todos os elementos da página e, em seguida, faz seu trabalho se o seletor corresponder. Chamei a classe CSS de "mouseover" em vez de "hover", porque não queria que nenhum leitor de CSS lesse ": hover" onde escrevi ".hover".

toon81
fonte
0

Aqui está minha solução: http://jsfiddle.net/agamemnus/g56aw709/-- código abaixo.

Tudo o que se precisa fazer é converter o seu ": hover" em ".hover" ... é isso! A grande diferença entre isso e o resto é que também funcionará em seletores de elementos não singulares, como .my_class > *:hover {.

handle_css_hover_effects ()

function handle_css_hover_effects (init) {
 var init = init || {}
 var handle_touch_events = init.handle_touch_events || true
 var handle_mouse_events = init.handle_mouse_events || true
 var hover_class         = init.hover_class         || "hover"
 var delay_preferences   = init.delay_preferences   || {touch: {add: 500, remove: 500}}
 function default_handler (curobj, input_type, op) {
  var hovered_element_selector = "*" + ((op == "add") ? ":" : ("." + hover_class))
  var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll(hovered_element_selector))
  var modified_list = []
  while (true) {
   if ((curobj == null) || (curobj == document.documentElement)) break
   if (hovered_elements.indexOf(curobj) != -1) modified_list.push (curobj)
   curobj = curobj.parentNode
  }
  function do_hover_change () {modified_list.forEach (function (curobj) {curobj.classList[op](hover_class)})}
  if ((!delay_preferences[input_type]) || (!delay_preferences[input_type][op])) {
   do_hover_change ()
  } else {
   setTimeout (do_hover_change, delay_preferences[input_type][op])
  }
 }

 if (handle_mouse_events) {
  document.body.addEventListener ('mouseover' , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "add")})
  document.body.addEventListener ('mouseout'  , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
  document.body.addEventListener ('click'     , function (evt) {var curobj = evt.target; default_handler (curobj, "mouse", "remove")})
 }

 if (handle_touch_events) {
  document.body.addEventListener ('touchstart', function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "add")})
  document.body.addEventListener ('touchend'  , function (evt) {var curobj = evt.target; default_handler (curobj, "touch", "remove")})
  document.body.addEventListener ('touchmove',  function (evt) {
   var curobj = evt.target
   var hovered_elements = Array.prototype.slice.call(document.body.querySelectorAll("*:hover"))
   var lastobj = null
   evt = evt.changedTouches[0]
   var elements_at_point = get_elements_at_point (evt.pageX, evt.pageY)
   // Get the last element that isn't at the current point but is still hovered over, and remove only its hover attribute.
   while (true) {
    if ((curobj == null) || (curobj == document.documentElement)) break
    if ((hovered_elements.indexOf(curobj) != -1) && (elements_at_point.indexOf(curobj) == -1)) lastobj = curobj
    curobj = curobj.parentNode
   }
   if (lastobj == null) return
   if ((!delay_preferences.touch) || (!delay_preferences.touch.remove)) {
    lastobj.classList.remove(hover_class)
   } else {
    setTimeout (function () {lastobj.classList.remove(hover_class)}, delay_preferences.touch.remove)
   }

   function get_elements_at_point (x, y) {
    var el_list = [], pe_list = []
    while (true) {
     var curobj = document.elementFromPoint(x, y)
     if ((curobj == null) || (curobj == document.documentElement)) break
     el_list.push (curobj); pe_list.push (curobj.style.pointerEvents)
     curobj.style.pointerEvents = "none"
    }
    el_list.forEach (function (current_element, i) {current_element.style.pointerEvents = pe_list[i]})
    return el_list
   }
  })
 }
}
Agamemnus
fonte
0

Inclua Modernizr em sua página e defina seus estados de foco como este:

html.no-touchevents .box:hover {
    background: blue;
}
Jonathan Potter
fonte
0

Olá, pessoa do futuro, você provavelmente deseja usar a consulta de mídia pointere / ou hover. A handheldconsulta de mídia foi descontinuada.

/* device is using a mouse or similar */
@media (pointer: fine) {
  a:hover {
    background: red;
  }
}
olanod
fonte
-1

Experimente esta solução jquery de 2019 fácil, embora já exista há algum tempo;

  1. adicione este plugin ao head:

    src="https://code.jquery.com/ui/1.12.0/jquery-ui.min.js"

  2. adicione isso a js:

    $("*").on("touchend", function(e) { $(this).focus(); }); //applies to all elements

  3. algumas variações sugeridas para isso são:

    $(":input, :checkbox,").on("touchend", function(e) {(this).focus);}); //specify elements
    
    $("*").on("click, touchend", function(e) { $(this).focus(); });  //include click event`
    
    css: body { cursor: pointer; } //touch anywhere to end a focus`

Notas

  • coloque o plugin antes do bootstrap.js, se aplicável, para evitar afetar as dicas de ferramentas
  • testado apenas no iphone XR ios 12.1.12 e ipad 3 ios 9.3.5, usando Safari ou Chrome.

Referências:

https://code.jquery.com/ui/

https://api.jquery.com/category/selectors/jquery-selector-extensions/

Darren
fonte