tl; dr use isso: https://jsfiddle.net/57tmy8j3/
Se você está interessado no porquê ou em que outras opções existem, continue lendo.
Quick'n'dirty - remove: pairar estilos usando JS
Você pode remover todas as regras CSS que contêm :hover
Javascript. Isso tem a vantagem de não precisar tocar em CSS e ser compatível mesmo com navegadores mais antigos.
function hasTouch() {
return 'ontouchstart' in document.documentElement
|| navigator.maxTouchPoints > 0
|| navigator.msMaxTouchPoints > 0;
}
if (hasTouch()) { // remove all the :hover stylesheets
try { // prevent exception on browsers not supporting DOM styleSheets properly
for (var si in document.styleSheets) {
var styleSheet = document.styleSheets[si];
if (!styleSheet.rules) continue;
for (var ri = styleSheet.rules.length - 1; ri >= 0; ri--) {
if (!styleSheet.rules[ri].selectorText) continue;
if (styleSheet.rules[ri].selectorText.match(':hover')) {
styleSheet.deleteRule(ri);
}
}
}
} catch (ex) {}
}
Limitações: as folhas de estilo devem estar hospedadas no mesmo domínio (isso significa que não há CDNs). Desativa o foco em dispositivos mistos de mouse e toque como o Surface ou iPad Pro, o que prejudica o UX.
Somente CSS - use consultas de mídia
Coloque todas as suas regras: hover em um @media
bloco:
@media (hover: hover) {
a:hover { color: blue; }
}
ou, como alternativa, substitua todas as suas regras de foco instantâneo (compatíveis com navegadores mais antigos):
a:hover { color: blue; }
@media (hover: none) {
a:hover { color: inherit; }
}
Limitações: funciona apenas no iOS 9.0+, Chrome para Android ou Android 5.0+ ao usar o WebView. hover: hover
quebra os efeitos de pairar em navegadores antigos, hover: none
precisa substituir todas as regras CSS definidas anteriormente. Ambos são incompatíveis com dispositivos mistos de mouse e toque .
O mais robusto - detectar toque via JS e preceder CSS: regras de foco
Este método precisa anexar todas as regras de foco com body.hasHover
. (ou um nome de classe de sua escolha)
body.hasHover a:hover { color: blue; }
A hasHover
classe pode ser adicionada usando hasTouch()
o primeiro exemplo:
if (!hasTouch()) document.body.className += ' hasHover'
No entanto, isso deve ter as mesmas desvantagens dos dispositivos de toque misto dos exemplos anteriores, o que nos leva à solução definitiva. Ative efeitos de foco instantâneo sempre que um cursor do mouse for movido, desative efeitos de foco instantâneo sempre que um toque for detectado.
function watchForHover() {
// lastTouchTime is used for ignoring emulated mousemove events
let lastTouchTime = 0
function enableHover() {
if (new Date() - lastTouchTime < 500) return
document.body.classList.add('hasHover')
}
function disableHover() {
document.body.classList.remove('hasHover')
}
function updateLastTouchTime() {
lastTouchTime = new Date()
}
document.addEventListener('touchstart', updateLastTouchTime, true)
document.addEventListener('touchstart', disableHover, true)
document.addEventListener('mousemove', enableHover, true)
enableHover()
}
watchForHover()
Isso deve funcionar basicamente em qualquer navegador e habilita / desabilita os estilos de foco, conforme necessário.
Aqui está o exemplo completo - moderno: https://jsfiddle.net/57tmy8j3/
Legado (para uso com navegadores antigos): https://jsfiddle.net/dkz17jc5/19/