¿Puedo deshabilitar un CSS: efecto de desplazamiento a través de JavaScript?

99

Estoy tratando de evitar que el navegador use el :hoverefecto de CSS, a través de JavaScript.

He configurado los estilos ay a:hoveren mi CSS, porque quiero un efecto de desplazamiento, si JS no está disponible. Pero si JS está disponible, quiero sobrescribir mi efecto de desplazamiento CSS con uno más suave (usando el complemento de color jQuery, por ejemplo).

Probé esto:

$("ul#mainFilter a").hover(
     function(e){ e.preventDefault(); ...do my stuff... }, 
     function(e){ e.preventDefault(); ...do my stuff... });

También lo probé return false;, pero no funciona.

Aquí hay un ejemplo de mi problema: http://jsfiddle.net/4rEzz/ . El enlace debería desaparecer sin volverse gris.

Como lo mencionó fudgey, una solución sería restablecer los estilos de desplazamiento usando .css()pero tendría que sobrescribir cada propiedad, especificada en el CSS (ver aquí: http://jsfiddle.net/raPeX/1/ ). Busco una solución genérica.

¿Alguien sabe como hacer esto?

PD: No quiero sobrescribir todos los estilos que he configurado para el hover.

meo
fuente

Respuestas:

136

No hay una solución genérica de JavaScript pura, me temo. JavaScript no puede desactivar el :hoverestado de CSS en sí.

Sin embargo, puede probar la siguiente solución alternativa. Si no le importa jugar un poco en su HTML y CSS, le ahorra tener que restablecer cada propiedad CSS manualmente a través de JavaScript.

HTML

<body class="nojQuery">

CSS

/* Limit the hover styles in your CSS so that they only apply when the nojQuery 
class is present */

body.nojQuery ul#mainFilter a:hover {
    /* CSS-only hover styles go here */
}

JavaScript

// When jQuery kicks in, remove the nojQuery class from the <body> element, thus
// making the CSS hover styles disappear.

$(function(){}
    $('body').removeClass('nojQuery');
)
Paul D. Waite
fuente
5
Me gusta más esta solución que las soluciones noscript porque funciona cuando el CSS está completamente contenido en archivos externos, y también funciona durante la carga de la página, si el CSS se carga primero pero el JS no se carga hasta más tarde. El uso de jQuery para "mejorar progresivamente" las cosas a menudo da como resultado páginas que no funcionan bien si hace clic en las cosas antes de que termine de cargarse. Incluso con un navegador rápido en un enlace rápido, veo esto mucho.
Mr. Shiny and New 安 宇
@Señor. Brillante y nuevo: estoy de acuerdo, ¡me gusta más esto que mi solución también! No estoy seguro de por qué no noté la elegancia de este antes ...
Josh
3
“Me gusta más esta solución que las soluciones noscript porque funciona cuando el CSS está contenido por completo en archivos externos”, también lo hace la <noscript>solución. Simplemente coloque <link>etiquetas dentro de su <noscript>, en lugar de <style>etiquetas. Sin embargo, mi solución le permite mantener todo dentro de un archivo de hoja de estilo en lugar de varios archivos.
Paul D. Waite
no es exactamente lo que estaba buscando, pero creo que esta solución es el mejor compromiso. Gracias a todos ustedes
meo
también puede copiar el mismo estilo con un nombre diferente y usando jquery seleccionar todos los elementos con esa clase y eliminar la clase y reemplazar con la clase de copia.
chepe263
14

Use una segunda clase que solo tenga asignado el hover:

HTML

 <a class="myclass myclass_hover" href="#">My anchor</a>

CSS

 .myclass { 
   /* all anchor styles */
 }
 .myclass_hover:hover {
   /* example color */
   color:#00A;
 }

Ahora puede usar Jquery para eliminar la clase, por ejemplo, si se ha hecho clic en el elemento:

JQUERY

 $('.myclass').click( function(e) {
    e.preventDefault();
    $(this).removeClass('myclass_hover');
 });

Espero que esta respuesta sea útil.

Kai Noack
fuente
3
más 1. no es ortodoxo, pero resuelve el problema de una manera bastante sublime.
jim tollan
11

Puede manipular las hojas de estilo y las reglas de la hoja de estilo con javascript.

var sheetCount = document.styleSheets.length;
var lastSheet = document.styleSheets[sheetCount-1];
var ruleCount;
if (lastSheet.cssRules) { // Firefox uses 'cssRules'
    ruleCount = lastSheet.cssRules.length;
}
else if (lastSheet.rules) { / /IE uses 'rules'
    ruleCount = lastSheet.rules.length;
}
var newRule = "a:hover { text-decoration: none !important; color: #000 !important; }";
// insert as the last rule in the last sheet so it
// overrides (not overwrites) previous definitions
lastSheet.insertRule(newRule, ruleCount);

Hacer que los atributos! Sean importantes y hacer de esta la última definición de CSS debe anular cualquier definición anterior, a menos que una sea más específica. Puede que tenga que insertar más reglas en ese caso.

Stephen P
fuente
1
O puede poner todas las reglas de noscript en una hoja de estilo y luego deshabilitar la hoja de estilo desde javascript.
Sean Hogan
2
¿O poner su <link>etiqueta de hoja de estilo noscript dentro de un <noscript>elemento? Eso funcionaría, ¿verdad?
Paul D. Waite
1
O elimine la regla "ofensiva": developer.mozilla.org/en/DOM/stylesheet.deleteRule
RoToRa
1
Incluso IE5 puede hacerlo. Su método se llama de manera diferente, pero debería funcionar: msdn.microsoft.com/en-us/library/ms531195%28v=vs.85%29.aspx . No he comprobado otros navegadores, pero supongo que todos los navegadores modernos implementan el estándar.
RoToRa
En Firefox obtengoError: The operation is insecure.
Alex W
11

Esto es similar a la respuesta de aSeptik, pero ¿qué pasa con este enfoque? Envuelva el código CSS que desea deshabilitar usando JavaScript en <noscript>etiquetas. De esa forma, si javaScript está desactivado, el CSS:hover se utilizará ; de lo contrario, se utilizará el efecto JavaScript.

Ejemplo:

<noscript>
<style type="text/css">
ul#mainFilter a:hover {
  /* some CSS attributes here */
}
</style>
</noscript>
<script type="text/javascript">
$("ul#mainFilter a").hover(
     function(o){ /* ...do your stuff... */ }, 
     function(o){ /* ...do your stuff... */ });
</script>
Josh
fuente
4

He utilizado el not()operador de CSS y jQuery addClass()función. Aquí hay un ejemplo, cuando hace clic en un elemento de la lista, ya no se desplaza:

Por ejemplo:

HTML

<ul class="vegies">
    <li>Onion</li>
    <li>Potato</li>
    <li>Lettuce</li>
<ul>

CSS

.vegies li:not(.no-hover):hover { color: blue; }

jQuery

$('.vegies li').click( function(){
    $(this).addClass('no-hover');
});
Atún frío
fuente
3

Usaría CSS para evitar que el evento: hover cambie la apariencia del enlace.

a{
  font:normal 12px/15px arial,verdana,sans-serif;
  color:#000;
  text-decoration:none;
}

Este CSS simple significa que los enlaces siempre serán negros y no estarán subrayados. No puedo decir a partir de la pregunta si el cambio en la apariencia es lo único que desea controlar.

Christopher Altman
fuente
es bueno que haya un efecto: hover si JS no está disponible en un cliente. Pero si es así, necesito sobrescribirlo. He configurado una clase: hover en mi css, solo quiero deshabilitarla.
meo
@meo: no puede deshabilitar las clases de CSS psuedo, pero puede anularlas configurando todos los estilos de enlace para que tengan la misma apariencia / parámetros. Tanto esta respuesta como mi respuesta hacen esto, solo que de diferentes maneras.
Mottie
3

Recomendaría reemplazar todas las :hoverpropiedades :activecuando detecte que el dispositivo es compatible con el tacto. Simplemente llame a esta función cuando lo haga como touch().

function touch() {
  if ('ontouchstart' in document.documentElement) {
    for (var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
      var sheet = document.styleSheets[sheetI];
      if (sheet.cssRules) {
        for (var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
          var rule = sheet.cssRules[ruleI];

          if (rule.selectorText) {
            rule.selectorText = rule.selectorText.replace(':hover', ':active');
          }
        }
      }
    }
  }
}
Shobhit Sharma
fuente
Funciona muy bien para mi. ¡Gracias!
Inversión
1

Intente simplemente configurar el color del enlace:

$("ul#mainFilter a").css('color','#000');

Editar: o mejor aún, use el CSS, como sugirió Christopher

Pajeño
fuente
jsfiddle.net/raPeX He hecho un ejemplo. Funciona, pero es un poco estúpido hacer eso. ¿Tendría que recuperar todos los valores de CSS y agregarlos como estilo? Debe haber una mejor manera. No quiero hacer eso. pero +1 para la pista
meo
Hola Meo, no, no, mi código anterior estaba dirigido a un enlace específico ya que eso es lo que pensé que querías. ¿Podría generalizarlo más simplemente usando en alugar de ul#mainFilter asi eso es lo que quiere decir, o está diciendo que cada enlace en la página es de un color diferente?
Mottie
Actualicé
Mottie
Ya lo tengo, gracias. Pero el problema es que no solo cambia el color en mi desplazamiento, a veces es el fondo, el borde, a veces incluso la altura de la línea. Es por eso que sería más fácil para mí simplemente evitar el hover, den para sobrescribir cada efecto de hover.
meo
Parche parcial para esta idea: podría crear css una regla que seleccione para a.jsOverride:hoverque anule todas las características de css, por lo que js solo tendría que agregar esa jsOverrideclase a todos los enlaces cuando se cargue la página ...
grossvogel
1

En realidad, otra forma de resolver esto podría ser sobrescribir el CSS con insertRule.

Da la capacidad de inyectar reglas CSS a una hoja de estilo nueva o existente. En mi ejemplo concreto, se vería así:

//creates a new `style` element in the document
var sheet = (function(){
  var style = document.createElement("style");
  // WebKit hack :(
  style.appendChild(document.createTextNode(""));
  // Add the <style> element to the page
  document.head.appendChild(style);
  return style.sheet;
})();

//add the actual rules to it
sheet.insertRule(
 "ul#mainFilter a:hover { color: #0000EE }" , 0
);

Demostración con mi ejemplo original de 4 años: http://jsfiddle.net/raPeX/21/

meo
fuente