2008-11-22 32 views
105

Estoy buscando una forma de cambiar las reglas de CSS para los selectores de pseudo-clase (como: enlace,: hover, etc.) desde JavaScript.Establecer reglas de pseudoclase de CSS desde JavaScript

Por lo tanto, un análogo del código CSS: a:hover { color: red } en JS.

No he podido encontrar la respuesta en ningún otro lado; si alguien sabe que esto es algo que los navegadores no admiten, también sería un resultado útil.

Respuesta

168

No se puede aplicar estilo a una pseudoclase en un elemento particular solo, de la misma forma que no se puede tener una pseudoclase en un atributo inline style = "..." (ya que no hay selector)

Puede hacerlo mediante la alteración de la hoja de estilo, por ejemplo mediante la adición de la regla:

#elid:hover { background: red; } 

asumiendo cada elemento que desea modificar tiene un identificador único para que pueda ser seleccionada.

En teoría el documento que desea es http://www.w3.org/TR/DOM-Level-2-Style/Overview.html que significa que puede (dada una hoja de estilo pre-existentes incrustado o vinculado) utilizando una sintaxis como:

document.styleSheets[0].insertRule('#elid:hover { background-color: red; }', 0); 
document.styleSheets[0].cssRules[0].style.backgroundColor= 'red'; 

IE, por supuesto, requiere su propia sintaxis:

document.styleSheets[0].addRule('#elid:hover', 'background-color: red', 0); 
document.styleSheets[0].rules[0].style.backgroundColor= 'red'; 

Los navegadores antiguos y menores probablemente no admitan ninguna sintaxis. La creación de hojas de estilo dinámicas rara vez se realiza porque es bastante molesto acertar, raramente necesario e históricamente problemático.

+3

+1 materia misma utilidad – Anurag

+27

¿Por qué no esta elegida como respuesta? – SZH

+0

URL de referencia más específicas: - - - ​​ –

1

Como ya se mencionó, esto no es algo que los navegadores respalden.

Si no se te ocurren los estilos dinámicamente (es decir, quitándolos de una base de datos o algo), deberías poder solucionar esto agregando una clase al cuerpo de la página.

El css sería algo como:

a:hover { background: red; } 
.theme1 a:hover { background: blue; } 

Y el javascript para cambiar esto sería algo así como:

// Look up some good add/remove className code if you want to do this 
// This is really simplified 

document.body.className += " theme1"; 
+0

Por curiosidad, es 'element.classList.add' no muy bien soportado ? Sigo viendo gente haciendo 'element.className + ='. –

+2

classList es una característica más nueva y no parece que haya tenido un buen soporte hasta hace relativamente poco tiempo (consulte http://caniuse.com/classlist) –

16

Una función para hacer frente a las cosas entre navegadores:

addCssRule = function(/* string */ selector, /* string */ rule) { 
    if (document.styleSheets) { 
    if (!document.styleSheets.length) { 
     var head = document.getElementsByTagName('head')[0]; 
     head.appendChild(bc.createEl('style')); 
    } 

    var i = document.styleSheets.length-1; 
    var ss = document.styleSheets[i]; 

    var l=0; 
    if (ss.cssRules) { 
     l = ss.cssRules.length; 
    } else if (ss.rules) { 
     // IE 
     l = ss.rules.length; 
    } 

    if (ss.insertRule) { 
     ss.insertRule(selector + ' {' + rule + '}', l); 
    } else if (ss.addRule) { 
     // IE 
     ss.addRule(selector, rule, l); 
    } 
    } 
}; 
3

En lugar de establecer directamente reglas de pseudo-clase con javascript, puede establecer las reglas de manera diferente en diferentes archivos CSS, y luego use Javascript para desactivar una hoja de estilos y activar otra. Se describe un método en A List Apart (qv. Para más detalles).

Establecer los archivos CSS como,

<link rel="stylesheet" href="always_on.css"> 
<link rel="stylesheet" title="usual" href="preferred.css"> <!-- on by default --> 
<link rel="alternate stylesheet" title="strange" href="alternate.css"> <!-- off by default --> 

y luego alternar entre ellas usando javascript:

function setActiveStyleSheet(title) { 
    var i, a, main; 
    for(i=0; (a = document.getElementsByTagName("link")<i>); i++) { 
    if(a.getAttribute("rel").indexOf("style") != -1 
     && a.getAttribute("title")) { 
     a.disabled = true; 
     if(a.getAttribute("title") == title) a.disabled = false; 
    } 
    } 
} 
+0

¿Qué sucede si necesita cambiar dinamicamente la clase a un valor recuperado por una solicitud AJAX? No puede crear un archivo CSS ahora ... – andreszs

29

me tiró juntos un small library for this ya que yo creo que hay casos de uso válidos para la manipulación de hojas de estilo en JS. Razones:

  • Configuración de estilos que se deben calcular o recuperar, por ejemplo, establecer el tamaño de fuente preferido del usuario a partir de una cookie.
  • Configuración de estilos de comportamiento (no estéticos), especialmente para desarrolladores de widgets/complementos de UI. Las pestañas, los carruseles, etc., a menudo requieren un CSS básico para funcionar: no debe solicitar una hoja de estilo para la función central.
  • Mejor que los estilos en línea, ya que las reglas de CSS se aplican a todos los elementos actuales y futuros, y no saturan el HTML cuando se visualizan en Firebug/Developer Tools.
+3

Se ve muy bien –

4

Hay otra alternativa. En lugar de manipular las pseudo-clases directamente, crea clases reales que modelen las mismas cosas, como una clase "hover" o una clase "visitada". Estilo las clases con el habitual "." sintaxis y luego puede usar JavaScript para agregar o eliminar clases de un elemento cuando se desencadena el evento apropiado.

+1

Eso no funciona para: antes y después de las pseudo clases. – jbyrd

+0

Y eso no es aplicable para cambiar la imagen de fondo con un valor recuperado a través de AJAX. – andreszs

+1

@jbyrd, ': before' &': after' son pseudoelementos, no clases. –

6

Mi truco es usar un selector de atributos. Los atributos son más fáciles de configurar mediante javascript.

css

.class{ /*normal css... */} 
.class[special]:after{ content: 'what you want'} 

Javascript

function setSpecial(id){ document.getElementById(id).setAttribute('special', '1'); } 

html

<element id='x' onclick="setSpecial(this.id)"> ... 
+4

Esta solución usa jQuery: introducir una dependencia del tamaño de jQuery para algo tan simple como esto, cuando el que pregunta preguntó por Javascript puro, es malo. –

+0

Aunque actualmente prácticamente todos los sitios web usan jquery, lo modificaré para usar javascript puro. –

+1

Y exactamente cómo este método consigue cambiar los atributos CSS de .class [especial]: después del pseudo elemento, como, el color de fondo o cualquier otra cosa? – andreszs

-1

En jQuery se puede configurar fácilmente activable pseudo clases.

$("p").hover(function(){ 
$(this).css("background-color", "yellow"); 
}, function(){ 
$(this).css("background-color", "pink"); 
}); 
-1

Si utilizar reaccionar, hay algo llamado radium. Es tan útil aquí:

  • Add handlers to props if interactive styles are specified, e.g. onMouseEnter for :hover, wrapping existing handlers if necessary

  • If any of the handlers are triggered, e.g. by hovering, Radium calls setState to update a Radium-specific field on the components state object

  • On re-render, resolve any interactive styles that apply, e.g. :hover, by looking up the element's key or ref in the Radium-specific state
-1

aquí es una solución que incluye dos funciones: addCSSclass añade una nueva clase CSS al documento, y toggleClass lo convierte en

El ejemplo muestra la adición de una barra de desplazamiento personalizado a un div

// If newState is provided add/remove theClass accordingly, otherwise toggle theClass 
 
function toggleClass(elem, theClass, newState) { 
 
    var matchRegExp = new RegExp('(?:^|\\s)' + theClass + '(?!\\S)', 'g'); 
 
    var add = (arguments.length > 2 ? newState : (elem.className.match(matchRegExp) === null)); 
 

 
    elem.className = elem.className.replace(matchRegExp, ''); // clear all 
 
    if (add) elem.className += ' ' + theClass; 
 
} 
 

 
function addCSSclass(rules) { 
 
    var style = document.createElement("style"); 
 
    style.appendChild(document.createTextNode("")); // WebKit hack :(
 
    document.head.appendChild(style); 
 
    var sheet = style.sheet; 
 

 
    rules.forEach((rule, index) => { 
 
    try { 
 
     if ("insertRule" in sheet) { 
 
     sheet.insertRule(rule.selector + "{" + rule.rule + "}", index); 
 
     } else if ("addRule" in sheet) { 
 
     sheet.addRule(rule.selector, rule.rule, index); 
 
     } 
 
    } catch (e) { 
 
     // firefox can break here   
 
    } 
 
    
 
    }) 
 
} 
 

 
let div = document.getElementById('mydiv'); 
 
addCSSclass([{ 
 
    selector: '.narrowScrollbar::-webkit-scrollbar', 
 
    rule: 'width: 5px' 
 
    }, 
 
    { 
 
    selector: '.narrowScrollbar::-webkit-scrollbar-thumb', 
 
    rule: 'background-color:#808080;border-radius:100px' 
 
    } 
 
]); 
 
toggleClass(div, 'narrowScrollbar', true);
<div id="mydiv" style="height:300px;width:300px;border:solid;overflow-y:scroll"> 
 
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus 
 
    a diam volutpat, ullamcorper justo eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit 
 
    nec sodales sodales. Etiam eget dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. Lorem ipsum dolor sit amet, consectetur 
 
    adipiscing elit. Sed a eros metus. Nunc dui felis, accumsan nec aliquam quis, fringilla quis tellus. Nulla cursus mauris nibh, at faucibus justo tincidunt eget. Sed sodales eget erat consectetur consectetur. Vivamus a diam volutpat, ullamcorper justo 
 
    eu, dignissim ante. Aenean turpis tortor, fringilla quis efficitur eleifend, iaculis id quam. Quisque non turpis in lacus finibus auctor. Morbi ullamcorper felis ut nulla venenatis fringilla. Praesent imperdiet velit nec sodales sodales. Etiam eget 
 
    dui sollicitudin, tempus tortor non, porta nibh. Quisque eu efficitur velit. Nulla facilisi. Sed varius a erat ac volutpat. Sed accumsan maximus feugiat. Mauris id malesuada dui. 
 
</div>

Cuestiones relacionadas