Modificar estilos CSS vía Javascript es una habilidad que debe tener todo desarrollador web que se precie. En este artículo repaso las diversas técnicas de manipulación del CSS, de un elemento HTML, o incluso de toda la página:
- Modificar una única propiedad CSS de un elemento.
- Manipular el atributo
class
del elemento. - Técnicas avanzadas, como inyección de nodos
style
o el reemplazo de toda una hoja de estilos externa por otra distinta.
Todo esto, sin necesariamente sacrificar compatibilidad, accesibilidad y rendimiento… ¡Al lío!
Cambiar una única propiedad CSS
Supongamos que, por algún motivo, quiero que este párrafo que estás leyendo pase a tener un fondo de color fucsia. Pongamos que su HTML es algo así:
<p id="intro">Supongamos que, por algún motivo,…</p>
En tal caso, perpetrar el cambio de color sería tan sencillo como:
var intro = document.getElementById('intro');
intro.style.backgroundColor = '#FF00FF';
En Javascript, todo elemento HTML tiene una propiedad style
que representa a sus estilos en línea. Es decir, después de ejecutar la anterior línea de código, el HTML resultante sería más o menos el siguiente:
<p id="intro" style="background-color: rgb(255, 0, 255);">
Supongamos que, por algún motivo,…
</p>
Si decidimos deshacer el entuerto, podemos eliminar todo rastro de fucsia asignando null
a la propiedad:
intro.style.backgroundColor = null;
Nota: La MDN mantiene una lista de referencia de las propiedades CSS más frecuentes, con su correspondiente notación en Javascript (que es la misma, pero usando camellúsculas).
La propiedad style
contiene también el atributo cssText
, que permite asignar varias propiedades CSS al mismo tiempo, asignándole una cadena (pero, ojo, porque esto sobreescribirá cualquier otro estilo en línea preexistente):
intro.style.cssText = 'background-color: black; color: white;';
En jQuery puedes usar el método .css() para asignar valores a una o varias propiedades CSS:$(this).css("background-color", "#FF00FF");
$(this).css({ "background-color": "black", "color": "white" });
La diferencia con la propiedad style
es que el método .css()
, cuando se usa para consultar el valor actual de una propiedad, no devuelve el valor del estilo en línea, sino el del estilo computado (es decir, el «definitivo» que el navegador usará para presentar el elemento).
El problema de manipular el objeto style
es que puedes terminar teniendo en tu código Javascript demasiada información relativa a la presentación, cuando lo ideal es que de la presentación se encarguen las hojas de estilo CSS, y el Javascript se ocupe solamente de la semántica del HTML.
Para esta separación de intereses, la técnica más apropiada es la que explico a continuación.
Manipular la(s) clase(s) CSS de un elemento HTML
Digamos que en nuestra hoja de estilo externa tenemos la siguiente clase:
.negativo {
background-color: black;
color: white;
}
En cualquier momento podremos asignar esta clase a nuestro sufrido párrafo introductorio, tal que así:
var intro = document.getElementById('intro');
intro.className = 'negativo';
El resultado será:
<p id="intro" class="negativo">Supongamos que, por algún motivo,…</p>
Al no ser más que la representación del atributo HTML class
, también puede usarse className
para asignar varias clases a la vez, o para eliminarlas (asignando la cadena vacía).
En lugar de className
, también se puede usar el objeto classList
, que permite añadir, eliminar, alternar y consultar clases CSS cómodamente:
intro.classList.add('gatitos', 'ositos');
intro.classList.remove('ositos');
intro.classList.toggle('gatitos'); // Si tiene "gatitos" bórralos, si no añádelos
console.log(intro.classList.contains('gatitos')); // → false
La única pega es que classList
no funciona (o funciona con limitaciones) en navegadores prehistóricos, como IE9. Si necesitas ofrecer compatibilidad con estos dinosaurios, tus opciones son, o bien usar exclusivamente className
, o bien incorporar el correspondiente polyfill.
jQuery incluye los correspondientes addClass()
, removeClass(),
toggleClass()
y hasClass()
.
En concreto, hay bastantes casos de usos típicos del método toggle()
(activo/inactivo, visible/invisible, etc.). Por esta razón, siempre tengo a mano una funcioncita que cubre estos casos, y funciona en cualquier navegador:
Alternar hojas de estilo externas
Aquí ya entramos en terreno avanzado. Existe la posibilidad de sustituir toda una hoja de estilo, por ejemplo estilo_moderno.css
por estilo_retro.css
.
Esto permitiría cambiar dinámicamente todo el diseño, o «tema», de una página, al estilo CSS Zen Garden (lo cual raramente es necesario, pero mola un montón).
Lo más cómodo, en este caso, es tener identificado el correspondiente elemento <link>
mediante un atributo id
:
<link id="estilos" rel="stylesheet" href="css/moderno.css">
Con esto, solo nos quedaría asignar la nueva ruta al atributo href
del susodicho elemento:
document.getElementById('estilos').href = 'css/retro.css';
Al ejecutarse esta línea, el navegador descargará y aplicará la nueva hoja de estilo, sustituyendo a la anterior. ¡Magia!
En jQuery, la línea equivalente podría ser:$('#estilos').attr('href', 'css/retro.css');
Notas
Un par de consejillos para terminar:
- Si tu proyecto no usa jQuery, quizá no te merezca la pena incluirlo solo para este tipo de cosas.
- Quizá quieras echar un vistazo a
querySelector()
como alternativa agetElementById()
en algunos casos.
Mujy buenos tips para trabajar con css’s me sirvió mucho tu artículo.
Cuánto me alegro, muchas gracias por tu comentario. :_)
Buen contenido. Y aunque paresca una niñada, como puedo cambiar el estilo con javascript de unos datos que se genera automaticamente.
Dicho de otra forma. En el html no existen. Solo es generado por javascript y si se necesitarian poner color o tamaño. Como se provederia a hacer?.
El caso de HTML añadido dinámicamente no es muy diferente. La mejor práctica es añadirlo con algún atributo que nos permita identificarlo fácilmente más adelante, típicamente el atributo ID. Por ejemplo:
muchas gracias
Hola ¡¡¡ ¿Como pasas el parametro de p a la funcion alternarClase ?
Lo he intentando pero nada
Haz Click Aqui ¡¡
Haz Click Aqui ¡¡
const elements = document.getElementsByTagName(«p»);
Haz Click Aqui ¡¡
Hola, Manolo:
¿Quizá le estás pasando tu constante «elements»?
document.getElementsByTagName() siempre devuelve una colección de elementos, pero la función alternarClase() espera recibir un elemento individual (algo así como elements[0] o elements.item(0)).