Deshabilitar los efectos de desplazamiento en los navegadores móviles

113

Estoy escribiendo un sitio web destinado a ser utilizado tanto desde computadoras de escritorio como desde tabletas. Cuando se visita desde un escritorio, quiero que las áreas de la pantalla en las que se puede hacer clic se iluminen con :hoverefectos (color de fondo diferente, etc.) Con una tableta, no hay mouse, por lo que no quiero ningún efecto de desplazamiento.

El problema es que, cuando toco algo en la tableta, el navegador evidentemente tiene algún tipo de "cursor de mouse invisible" que se mueve a la ubicación que toqué y luego lo deja allí, por lo que lo que acabo de tocar se ilumina con un efecto de desplazamiento hasta que toque otra cosa.

¿Cómo puedo obtener los efectos de desplazamiento cuando estoy usando el mouse, pero suprimirlos cuando estoy usando la pantalla táctil?

En caso de que alguien estuviera pensando en sugerirlo, no quiero usar el rastreo de agentes de usuario. El mismo dispositivo podría tener una pantalla táctil y un mouse (tal vez no sea tan común hoy, pero mucho más en el futuro). No me interesa el dispositivo, me interesa cómo se utiliza actualmente: ratón o pantalla táctil.

Ya he intentado enganchar los touchstart, touchmove, y touchendeventos y llamando preventDefault()en todos ellos, lo que hace suprimir el "cursor del ratón invisible" una parte del tiempo; pero si toco rápidamente hacia adelante y hacia atrás entre dos elementos diferentes, después de algunos toques comenzará a mover el "cursor del mouse" e iluminará los efectos de desplazamiento de todos modos; es como si mi preventDefaultno siempre fuera un honor. No los aburriré con los detalles a menos que sea necesario; ni siquiera estoy seguro de que ese sea el enfoque correcto a seguir; si alguien tiene una solución más simple, soy todo oídos.


Editar: esto se puede reproducir con CSS estándar del pantano :hover, pero aquí hay una reproducción rápida como referencia.

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

Si pasa el mouse sobre cualquiera de los cuadros, obtendrá un fondo azul, que quiero. Pero si toca cualquiera de las casillas, también obtendrá un fondo azul, que es lo que estoy tratando de evitar.

También publiqué una muestra aquí que hace lo anterior y también engancha los eventos del mouse de jQuery. Se puede utilizar para ver que los eventos Tap también se disparará mouseenter, mousemovey mouseleave.

Joe White
fuente
7
@Blender, ¿leíste la pregunta? Ya expliqué por qué el rastreo de agentes de usuario es una mala elección.
Joe White
Hola Joe, ¿encontraste alguna solución para esto?
Ismatjon
Estaba buscando este tipo de pregunta, ¡me alegro de haberla encontrado!
agpt
Consulte también esta pregunta, que trata sobre la desactivación del desplazamiento en cualquier dispositivo táctil, no solo en dispositivos móviles: stackoverflow.com/questions/23885255/…
blade

Respuestas:

83

De tu pregunta deduzco que tu efecto de desplazamiento cambia el contenido de tu página. En ese caso, mi consejo es:

  • Agregue efectos de desplazamiento en touchstarty mouseenter.
  • Retire la libración efectos en mouseleave, touchmovey click.

Alternativamente, puede editar su página para que no haya cambios de contenido.

Antecedentes

Para simular un mouse, los navegadores como Webkit mobile activan los siguientes eventos si un usuario toca y suelta un dedo en la pantalla táctil (como iPad) (fuente: Touch And Mouse en html5rocks.com):

  1. touchstart
  2. touchmove
  3. touchend
  4. Retraso de 300 ms, donde el navegador se asegura de que sea un solo toque, no un doble toque
  5. mouseover
  6. mouseenter
    • Nota : Si un evento mouseover, mouseentero mousemovecambia el contenido de la página, los siguientes eventos nunca se activan.
  7. mousemove
  8. mousedown
  9. mouseup
  10. click

No parece posible simplemente decirle al navegador web que omita los eventos del mouse.

Lo que es peor, si un evento de mouseover cambia el contenido de la página, el evento de clic nunca se activa, como se explica en la Guía de contenido web de Safari - Manejo de eventos , en particular la figura 6.4 en Eventos de un dedo . Qué es exactamente un "cambio de contenido", dependerá del navegador y la versión. Descubrí que para iOS 7.0, un cambio en el color de fondo no es (¿o ya no?) Un cambio de contenido.

Solución explicada

Recordar:

  • Agregue efectos de desplazamiento en touchstarty mouseenter.
  • Retire la libración efectos en mouseleave, touchmovey click.

¡Tenga en cuenta que no hay ninguna acción en touchend!

Esto claramente funciona para eventos de mouse: mouseentery mouseleave(versiones ligeramente mejoradas de mouseovery mouseout) se activan, y agregan y eliminan el desplazamiento.

Si el usuario realmente clickes un enlace, el efecto de desplazamiento también se elimina. Esto asegura que se elimine si el usuario presiona el botón Atrás en el navegador web.

Esto también funciona para eventos táctiles: al inicio táctil, se agrega el efecto de desplazamiento. Se '' 'no' '' se quita al tocarlo. Se vuelve a agregar mouseentery, dado que esto no provoca cambios de contenido (ya se agregó), el clickevento también se dispara y el enlace se sigue sin necesidad de que el usuario vuelva a hacer clic.

El retraso de 300 ms que tiene un navegador entre un touchstartevento y el que clickse le da un buen uso porque el efecto de desplazamiento se mostrará durante este corto tiempo.

Si el usuario decide cancelar el clic, un movimiento del dedo lo hará con normalidad. Normalmente, esto es un problema ya que no mouseleavese dispara ningún evento y el efecto de desplazamiento permanece en su lugar. Afortunadamente, esto se puede solucionar fácilmente eliminando el efecto de desplazamiento en touchmove.

¡Eso es!

Tenga en cuenta que es posible eliminar el retraso de 300 ms , por ejemplo, utilizando la biblioteca FastClick , pero esto está fuera del alcance de esta pregunta.

Soluciones alternativas

Encontré los siguientes problemas con las siguientes alternativas:

  • detección del navegador: Extremadamente propenso a errores. Asume que un dispositivo tiene mouse o touch, mientras que una combinación de ambos se volverá cada vez más común cuando las pantallas táctiles sean prolíficas.
  • Detección de medios CSS: la única solución solo de CSS que conozco. Todavía es propenso a errores y aún asume que un dispositivo tiene mouse o touch, mientras que ambos son posibles.
  • Emular el evento de clic en touchend: Esto seguirá incorrectamente el enlace, incluso si el usuario solo quería desplazarse o hacer zoom, sin la intención de hacer clic en el enlace.
  • Usar una variable para suprimir los eventos del mouse: esto establece una variable touchendque se usa como una condición if en eventos posteriores del mouse para evitar cambios de estado en ese momento. La variable se restablece en el evento de clic. Vea la respuesta de Walter Roman en esta página. Esta es una solución decente si realmente no desea un efecto de desplazamiento en las interfaces táctiles. Desafortunadamente, esto no funciona si touchendse dispara a por otro motivo y no se dispara ningún evento de clic (por ejemplo, el usuario se desplazó o hizo zoom), y posteriormente está tratando de seguir el enlace con un mouse (es decir, en un dispositivo con interfaz de mouse y táctil ).

Otras lecturas

MacFreek
fuente
1
Buena respuesta. Usé tu violín para comenzar a crear mi propia solución. Sin embargo, a veces se necesita el toque final. (cuando un movimiento táctil no se ejecuta, es decir, cuando el usuario sale del documento en sí ...)
Agamemnus
Excelente respuesta, pero en la mayoría de los casos sugeriría usar en touchend lugar de touchstarten la mayoría de los casos para evitar activar acciones inmediatamente cuando el usuario intenta deslizar el dedo hacia arriba o hacia abajo en una página. Se siguen sucediendo, pero es menos probable que distraer o confundir (asumiendo que es algo inofensivo como mostrar una etiqueta, no es algo que el usuario tiene que saber que pasó)
user56reinstatemonica8
19

¿Cómo puedo obtener los efectos de desplazamiento cuando estoy usando el mouse, pero suprimirlos cuando estoy usando la pantalla táctil?

Tal vez no piense en ello tanto como suprimir los efectos de desplazamiento para las pantallas táctiles, sino como añadir efectos de desplazamiento para los eventos del ratón.

Si desea mantener los :hoverefectos en su CSS, puede especificar diferentes estilos para diferentes medios:

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

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

Excepto que, desafortunadamente, hay muchos dispositivos móviles que ignoran esto y solo usan las reglas de la pantalla. Afortunadamente, muchos de los navegadores más nuevos para dispositivos móviles / tabletas admiten algunas consultas de medios más sofisticadas:

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

Entonces, incluso si se ignora la parte de "pantalla" o "computadora de mano", el "ancho máximo" funcionará por usted. Simplemente podría suponer que cualquier cosa con una pantalla de menos de 800 píxeles debe ser una tableta o teléfono, y no usar efectos de desplazamiento. Para los pocos usuarios que usan un mouse en un dispositivo de baja resolución, no verían los efectos de desplazamiento, pero su sitio estaría bien de lo contrario.

¿Más información sobre consultas de medios? Hay muchos artículos sobre esto en línea; aquí hay uno: http://www.alistapart.com/articles/return-of-the-mobile-stylesheet

Si desplaza los efectos de desplazamiento fuera de su CSS y los aplica con JavaScript, entonces podría vincularse específicamente a los eventos del mouse, y / o nuevamente podría hacer algunas suposiciones solo en función del tamaño de la pantalla, siendo el "problema" del peor de los casos que algunos el usuario que usa un mouse pierde los efectos de desplazamiento.

nnnnnn
fuente
Me encantaría agregar efectos de desplazamiento solo para eventos de mouse. Pero los eventos táctiles emulan los eventos del mouse. Si engancho los eventos táctiles y llamo preventDefault(), eso a veces suprime los eventos del mouse, pero como dije en mi pregunta, no es confiable.
Joe White
6
En cuanto a las consultas de medios, ¿qué sucede cuando sale Windows 8 y las PC tienen pantallas táctiles y ratones? Si el usuario se desplaza con el mouse, verá el cursor del mouse y quiero los efectos de desplazamiento; si tocan con la pantalla táctil, no quiero los efectos de desplazamiento. Pero no he encontrado una forma confiable de detectar la diferencia entre el tacto y el mouse.
Joe White
Bueno, tal vez los desarrolladores de navegadores estén más motivados para hacer que la detección sea más consistente una vez que tengan un mayor número de usuarios en dispositivos con toque y mouse. ¿Pero por ahora? Estaría haciendo conjeturas según el tamaño de la pantalla, pero hay otros consejos en las otras respuestas. Lo siento, no puedo ayudar más.
nnnnnn
9

Escribí el siguiente JS para un proyecto reciente, que era un sitio de escritorio / móvil / tableta que tiene efectos de desplazamiento que no deberían aparecer al tacto.

El mobileNoHoverStatemódulo de abajo tiene una variable preventMouseover(declarado inicialmente como false), que se establece para truecuando un usuario dispara el touchstartevento en un elemento, $target.

preventMouseoverluego, se vuelve a configurar falsecada vez que se activa el mouseoverevento, lo que permite que el sitio funcione según lo previsto si un usuario utiliza tanto la pantalla táctil como el mouse.

Sabemos que mouseoverse activa después touchstartdebido al orden en el que se declaran 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
    };
}();

Luego, se crea una instancia del módulo más adelante en la línea:

mobileNoHoverState.init();
Walter Roman
fuente
"preventMouseover se vuelve a establecer en true cada vez que se activa el evento mouseover, lo que permite que el sitio funcione según lo previsto si un usuario utiliza tanto la pantalla táctil como el mouse". - Tu código no hace eso. ¿Me estoy perdiendo de algo?
Redtopia
@Redtopia ¡Gracias por el aviso! Actualicé la respuesta con el código que quedó fuera.
Walter Roman
No necesita punto y coma después de la declaración de función
nacholibre
@nacholibre Se ha implementado el uso adecuado del punto y coma
Walter Roman
6

Realmente quería una csssolución pura para esto, ya que esparcir una solución javascript pesada alrededor de todas mis vistas parecía una opción desagradable. Finalmente encontré la consulta @ media.hover , que puede detectar "si el mecanismo de entrada principal permite al usuario desplazarse sobre los elementos". Esto evita dispositivos táctiles donde "flotar" es más una acción emulada que una capacidad directa del dispositivo de entrada.

Entonces, por ejemplo, si tengo un enlace:

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

Entonces puedo diseñarlo con seguridad solo :hovercuando el dispositivo lo admita fácilmente con esto css:

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

Si bien la mayoría de los navegadores modernos admiten consultas de funciones de medios de interacción, algunos navegadores populares como IE y Firefox no lo hacen. En mi caso, esto funciona bien, ya que solo tenía la intención de admitir Chrome en el escritorio y Chrome y Safari en el móvil.

flintinatux
fuente
Buena solución que parece funcionar cuando emula dispositivos en herramientas de desarrollo de Chrome. Pero todavía no funciona para Chrome Android :-(
Sjeiti
Creo que esta es la solución más conveniente y correcta. Espero que se agregue pronto a los estándares del W3C.
GProst
5

Mi solución es agregar la clase css activa de desplazamiento a la etiqueta HTML y usarla al comienzo de todos los selectores de CSS con: desplazar y eliminar esa clase en el primer 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
fuente
En lugar de escuchar un evento táctil, puede probarlo 'ontouchstart' in window. Ej .if ('ontouchstart' in window) document.querySelector('html').classList.remove('hover-active');
Yuval A.
@YuvalA. La razón por la que estoy esperando el evento táctil es que hay dispositivos con puntero y soporte táctil, y el usuario está usando el puntero y no quiero quitar el hover. Es posible que el usuario use el toque y luego el puntero, pero no tengo mucho que hacer al respecto
Bnaya
2

Lo que he hecho para resolver el mismo problema es tener una función de detección (uso algo como este código ), ver si onTouchMove está definido, y si es así agrego la clase css "touchMode" al cuerpo, de lo contrario agrego " desktopMode ".

Luego, cada vez que algún efecto de estilo solo se aplica a un dispositivo táctil, o solo a un escritorio, la regla css se antepone con la clase apropiada:

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

Editar : esta estrategia, por supuesto, agrega algunos caracteres adicionales a su css, por lo que si le preocupa el tamaño de css, puede buscar las definiciones touchMode y desktopMode y ponerlas en diferentes archivos, para que pueda servir css optimizado para cada dispositivo tipo; o puede cambiar los nombres de las clases a algo mucho más corto antes de ir a prod.

Stein G. Strindhaug
fuente
2

Bien, tuve un problema similar pero logré solucionarlo con consultas de medios y CSS simple. Estoy seguro de que estoy rompiendo algunas reglas aquí, pero me está funcionando.

Básicamente, tuve que tomar una aplicación masiva que alguien hizo y hacerla receptiva. Usaron jQueryUI y me pidieron que no manipulara ninguno de sus jQuery, por lo que estaba restringido a usar CSS solo.

Cuando presioné uno de sus botones en el modo de pantalla táctil, el efecto de desplazamiento se dispararía durante un segundo antes de que la acción del botón tuviera efecto. Así es como lo arreglé.

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

       #buttonOne{
            height: 44px;
        }


        #buttonOne:hover{
            display:none;
        }
}   
Loco
fuente
2

En mi proyecto, resolvimos este problema usando https://www.npmjs.com/package/postcss-hover-prefix y https://modernizr.com/ Primero, posprocesamos los archivos css de salida con postcss-hover-prefix. Agrega .no-touchpara todas las hoverreglas 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;
}

se convierte en

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

En tiempo de ejecución Modernizragrega automáticamente clases css a htmletiquetas 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">

Dicho posprocesamiento de css más Modernizr deshabilita el desplazamiento para dispositivos táctiles y lo habilita para otros. De hecho, este enfoque se inspiró en Bootstrap 4, cómo resuelven el mismo problema: https://v4-alpha.getbootstrap.com/getting-started/browsers-devices/#sticky-hoverfocus-on-mobile

Stanislav Berkov
fuente
1

Puede activar el mouseLeaveevento siempre que toque un elemento en la pantalla táctil. Aquí hay una solución para todas las <a>etiquetas:

function removeHover() {
    var anchors = document.getElementsByTagName('a');
    for(i=0; i<anchors.length; i++) {
        anchors[i].addEventListener('touchstart', function(e){
            $('a').mouseleave();
        }, false);
    }
}
Dijo Kholov
fuente
JSHint dice "no haga funciones dentro de un bucle".
NetOperator Wibby
Es un truco. NO es un código reutilizable que pueda considerarse una buena práctica. @NetOperatorWibby
Dijo Kholov
Bueno, no es realmente útil publicar código que no puede considerarse una buena práctica. Es como poner una tirita en una herida de cuchillo.
NetOperator Wibby
1

Iv había encontrado 2 soluciones al problema, lo que implica que detecta el contacto con modernizr o algo más y establece una clase táctil en el elemento html.

Esto es bueno pero no se admite muy bien:

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

Pero esto tiene un muy buen soporte :

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

Funciona perfectamente para mí, hace que todos los efectos de desplazamiento sean como cuando tocas un botón, se iluminará pero no terminará con errores como el efecto de desplazamiento inicial para los eventos del mouse.

Detectando el toque de dispositivos no táctiles creo que modernizr ha hecho el mejor trabajo:

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

EDITAR

Encontré una solución mejor y más simple para este problema.

Cómo determinar si el cliente es un dispositivo táctil

Simon Dragsbæk
fuente
0

Podría ser útil ver su CSS, ya que parece un problema bastante extraño. Pero de todos modos, si está sucediendo y todo lo demás está bien, puede intentar cambiar el efecto de desplazamiento a javascript (también puede usar jquery). Simplemente, conéctese al evento mouseover o mejor aún mouseenter e ilumine su elemento cuando se active el evento.

Vea el último ejemplo aquí: http://api.jquery.com/mouseover/ , ¡podría usar algo similar para registrar cuando se desencadena el evento y continuar desde allí!

balach
fuente
Nada especial sobre el CSS; ver mi edición. Y ya lo intenté mouseenter; no dados. Al tocar, se mueve el "cursor del mouse invisible", por lo que se activa mouseentery mousemove(y mouseleavecuando se toca en otro lugar).
Joe White
0

Si está contento de usar JavaScript, puede usar Modernizr en su página. Cuando se carga la página, un navegador de pantalla no táctil tendrá la clase '.no-touch' agregada a la etiqueta html, pero para un navegador de pantalla táctil, la etiqueta html tendrá la clase '.touch' agregada a la etiqueta html .

Entonces es simplemente un caso de verificar si la etiqueta html tiene la clase no-touch antes de decidir agregar sus oyentes mouseenter y mouseleave.

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 un dispositivo de pantalla táctil, los eventos no tendrán oyentes, por lo que no obtendrá ningún efecto de desplazamiento cuando toque.

Stanz
fuente
Cuando se puede hacer con css, no use javascript (jquery), es un desperdicio de poder de computadora
Simon Dragsbæk
1
Más simple aún, en su CSS, podría definir reglas separadas para .touchy .no-touch. Reescribir su respuesta en CSS junto con Modernizer, html.no-touch .box:hover {background-color: "#0000ff"}y no definir nada para html.touch .box:hoverdebería funcionar, ya que el OP solo está tratando de evitar los dispositivos móviles :hover.
Walter Roman
0

En un proyecto que hice recientemente, resolví este problema con la función de eventos delegados de jQuery. Busca ciertos elementos usando un selector de jQuery y agrega / elimina una clase CSS a esos elementos cuando el mouse está sobre el elemento. Parece que funciona bien hasta donde he podido probarlo, que incluye IE10 en una computadora portátil con capacidad táctil que ejecuta 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 solución, por supuesto, requiere que modifiques tu CSS para eliminar los selectores ": hover" y contemplar de antemano qué elementos quieres que sean "hoverables".

Sin embargo, si tiene muchos elementos en su página (como varios miles), es posible que se ralentice un poco, porque esta solución detecta eventos de tres tipos en todos los elementos de la página, y luego hace lo suyo si el selector coincide. Llamé a la clase CSS "mouseover" en lugar de "hover", porque no quería que ningún lector de CSS leyera ": hover" donde escribí ".hover".

toon81
fuente
0

Aquí está mi solución: http://jsfiddle.net/agamemnus/g56aw709/-- código a continuación.

Todo lo que hay que hacer es convertir su ": hover" en ".hover" ... ¡eso es todo! La gran diferencia entre esto y el resto es que esto también funcionará en selectores de elementos no 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
fuente
0

Incluya Modernizr en su página y configure sus estados de desplazamiento como este en su lugar:

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

Hola persona del futuro, probablemente quieras usar la consulta de medios pointery / o hover. La handheldconsulta de medios quedó obsoleta.

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

Pruebe esta sencilla solución jquery 2019, aunque ha existido por un tiempo;

  1. agregue este complemento al encabezado:

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

  2. agregue esto a js:

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

  3. algunas variaciones sugeridas a esto son:

    $(":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 el complemento antes de bootstrap.js, si corresponde, para evitar afectar la información sobre herramientas
  • solo probado en iphone XR ios 12.1.12 y ipad 3 ios 9.3.5, usando Safari o Chrome.

Referencias:

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

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

darren
fuente