Tres técnicas sencillas para cambiar estilos CSS con Javascript

Cambiando el CSS de Isabel II con Javascript

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:

7 comentarios en “Tres técnicas sencillas para cambiar estilos CSS con Javascript”

  1. 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?.

    1. 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:

      // Creamos un elemento con id 'red' y lo añadimos al DOM
      var rojo = document.createElement('p');
      rojo.textContent = 'Quiero fondo rojo';
      rojo.setAttribute('id', 'red');
      document.body.appendChild(rojo);
      
      // Una vez en el DOM, es como cualquier otro elemento
      document.getElementById('red').style.backgroundColor = '#F00';
  2. 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 ¡¡

    1. 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)).

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.