Cómo cambiar la clase de elemento con JavaScript - className y classList

En este tutorial, veremos cómo cambiar la clase de un elemento en JavaScript usando className y classList para navegadores modernos, con ejemplos prácticos.

Introducción

El atributo clase en HTML se usa para definir una clase para uno o más elementos HTML. De esta manera, muchos elementos pueden pertenecer a la misma clase de elementos y compartir el mismo estilo en la hoja de estilo, por lo que no tiene que escribir el mismo estilo para cada elemento una y otra vez.

Dicho esto, a veces desea cambiar los estilos dinámicamente, dependiendo de la entrada del usuario. Por ejemplo, desea implementar el modo día/noche para su página web, lo que se puede hacer de manera efectiva cambiando la clase del elemento.

Esta es una tarea común cuando desea permitir que el usuario personalice cualquier aspecto de su aplicación. En esta guía, veremos cómo cambiar la clase de un elemento HTML en JavaScript.

Árbol DOM

El DOM o Document Object Model es una interfaz que crea una estructura de árbol a partir de XML o HTML. La jerarquía de los elementos del documento se representa a través del DOM. Un árbol se compone de nodos y ramas, donde los elementos son nodos y las relaciones de los elementos son ramas. En el árbol DOM, el nodo raíz es html, el primer elemento necesario para comenzar a marcar un documento HTML:

1
2
3
4
5
6
7
8
9
<!DOCTYPE HTML>
<html>
<head>
    <title>Web page title</title>
</head>
<body>
    <h1>Some heading</h1>
</body>
</html>

El árbol DOM para esta página se vería así:

Este es un árbol muy simple, pero el mismo proceso se aplica a cualquier página arbitrariamente compleja. Gracias al árbol DOM, a través de JavaScript, podemos acceder a todos los elementos HTML de la página, así como a las clases de elementos, ids, contenido y todos sus atributos. Incluso podemos añadir nuevos elementos y eliminar los antiguos. Podemos crear eventos para escucharlos y responder a ellos (es decir, cambiar el color de fondo cuando se hace clic en un botón).

Obtener los elementos

Ahora que sabemos que podemos obtener un elemento de HTML, veamos cómo hacer eso usando JavaScript. Para cambiar la clase de un elemento, primero tenemos que recuperarlo. Dependiendo del elemento, podemos obtenerlos a través de diferentes métodos:

  • getElementsByClassName(class_name) - devuelve una HTMLCollection que contiene elementos HTML cuyos nombres de clase son iguales a class_name.
  • getElementById(id_name) - devuelve un único elemento HTML cuyo id es igual a id_name.
  • getElementsByTagName(tag_name) - devuelve una HTMLCollection de elementos con una etiqueta tag_name.

Estaremos trabajando con este archivo HTML:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE HTML>
<html>
<head>
    <title>Web page title</title>
</head>
<body class="page-body">
    <h1 class="headings">Some heading</h1>
    <h3 class="headings">More of some heading</h3>
    <h5 class="headings">Another heading here</h5>
    
    <a href="https://www.google.com" id="link-to-google">Some random link</a>
    <ul>
        <li>Thing #1</li>
        <li>Thing #2</li>
        <li>Thing #3</li>
    </ul>
    
</body>
    <script src="script.js"></script>
</html>

Obtener elementos usando getElementsByClassName()

Hagamos el archivo script.js que se importa a nuestra página:

1
$ touch script.js

Y dentro de él, ubicaremos y recuperaremos los elementos que pertenecen a la clase de "títulos":

1
console.log(document.getElementsByClassName("headings"));

Dado que es probable que haya más de un elemento que pertenezca a la misma clase, esto devuelve una HTMLCollection:

1
2
3
4
5
HTMLCollection(3)
    - 0: h1.headings
    - 1: h3.headings
    - 2: h5.headings
    length: 3

Una HTMLCollection es una colección de elementos HTML, que ofrece una variedad de métodos para seleccionarlos de la colección, tales como:

  • className() - Devuelve una cadena que representa el nombre de la clase; Este método también se puede usar para establecer la clase de un elemento (que es exactamente lo que necesitamos).
  • innerHTML() - Dado que los elementos HTML se pueden anidar entre sí, si hay elementos anidados, este método los devolverá como HTML.
  • innerText() - Devuelve todo el texto dentro de un elemento (incluidos los elementos anidados).

También hay muchos eventos que podemos escuchar, como: onclick, ondblclick, onkeydown, onkeypress. Puedes encontrar más información sobre los eventos de JavaScript en la documentación oficial.

Obtener elementos usando getElementById()

Puedes capturar elementos por su id, a través del método getElementById():

1
console.log(document.getElementById("link-to-google"));

Lo que resulta en:

1
<a href="https://www.google.com" id="link-to-google">Some random link</a>

Obtener elementos usando getElementsByTagName()

Finalmente, también podemos encontrar elementos por su etiqueta, si no tienen clase o id. Esto devuelve una colección de elementos HTML, porque normalmente tiene más de uno con la misma etiqueta.

Ahora, si queremos obtener todos los elementos <li>, podemos buscar por la etiqueta li:

1
console.log(document.getElementsByTagName("li"));

Lo que resulta en:

1
2
3
4
HTMLCollection(3) [li, li, li]
    - 0: li
    - 1: li
    - 2: li

El valor devuelto es el mismo que getElementsByClassName, una HTMLCollection.

Independientemente del enfoque utilizado para obtener un elemento, ahora podemos cambiar su clase.

Cambiando la Clase de un Elemento usando JavaScript

Cambiando la Clase de Elemento con className

Vamos a crear una página index.html ficticia que contenga algunos datos. Permitiremos que el usuario cambie entre el "modo diurno" y el "modo nocturno", lo que cambia la paleta de colores utilizada en la página web. También necesitaremos un archivo script.js importado aquí, para buscar y cambiar los elementos, así como un archivo style.css que contendrá todo nuestro código de estilo.

Comencemos con index.html:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE HTML>
<html>
<head>
    <title>Day/night mode</title>
    <link rel="stylesheet" href="style.css"/>
</head>
<body class="page-body-day" id="page-body">

    <h1 class="main-heading-day" id="main-heading">Some heading</h1>
    <p>Dummy text, dummy text, dummy text</p>
    <p>Some more dummy text, more dummy text, more dummy text</p>
    

    <button onclick="switchMode()">Switch day/night mode</button>
</body>
    
<script src="script.js"></script>
</html>

Todos los elementos que cambiarán su apariencia cuando el usuario haga clic en el botón Cambiar modo día/noche tienen sus respectivos ids y se les asigna la clase elemento-día por defecto respectivamente.

Cada clase element-day tiene una alternativa element-night en el archivo style.css:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
.page-body-day {
    background-color: white;
    color: black;
}

.page-body-night {
    background-color: #02182B;
    color: yellow;
}

.main-heading-day {
    color: black;
}

.main-heading-night {
    color: yellow;
}

Ya que estaremos cambiando la clase de nuestros elementos, no queremos buscar por clase, de lo contrario, tendremos casos extremos. Querremos buscar por algo de valor fijo, que es el id, y luego verificar el nombre de clase de ese elemento, cambiándolo a la clase apropiada en el proceso:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function switchMode(){
    
    // Body switching
    if(document.getElementById("page-body").className == "page-body-day"){
        document.getElementById("page-body").className = "page-body-night";
    }else{
        document.getElementById("page-body").className = "page-body-day";
    }

    // Heading switching
    if(document.getElementById("main-heading").className == "main-heading-day"){
        document.getElementById("main-heading").className = "main-heading-night";
    }else{
        document.getElementById("main-heading").className = "main-heading-day";
    }

}

El className devuelve el nombre de la clase de ese elemento. Sin embargo, si le asignamos un nuevo valor, podemos actualizar efectivamente la propiedad clase de una etiqueta. Si el elemento tiene una clase elemento-día, la cambiaremos a elemento-noche y viceversa.

Al cambiar la propiedad color del cuerpo en CSS, estamos cambiando automáticamente todos los elementos que no tienen definido el atributo color (en nuestro caso, son nuestras etiquetas <p>). Cuando ocurre el cambio de clase, CSS comienza a leer las clases recién cambiadas y aplica estilos en consecuencia.

Sin embargo, este enfoque no es muy moderno y se usa principalmente para adaptarse a la funcionalidad retrasada de Internet Explorer 8 y 9.

Cambiando la Clase de Elemento con classList

Los navegadores de Internet más nuevos tienen soporte para una propiedad más nueva llamada classList. Lo que proporciona esta propiedad es una lista de todas las clases que se aplican a un determinado elemento HTML.

Nota: Internet Explorer 8 y 9 no son compatibles con classList.

classList tiene un par de métodos que podemos aprovechar:

  • add(class_name) - agrega una nueva clase class_name a la lista.
  • remove(class_name) - elimina una clase class_name de la lista.
  • toggle(class_name) - agrega la clase class_name si aún no está agregada; de lo contrario, la elimina.
  • contains(class_name) - comprueba si class_name está en la lista de clases aplicadas al elemento HTML.

Dicho esto, podemos reescribir el archivo script.js para usar estos métodos en su lugar:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
function switchMode(){    
    // Body switching
    if(document.getElementById("page-body").classList.contains("page-body-day")){
        document.getElementById("page-body").classList.remove("page-body-day");
        document.getElementById("page-body").classList.add("page-body-night");
    } else{
        document.getElementById("page-body").classList.remove("page-body-night");
        document.getElementById("page-body").classList.add("page-body-day");
    }

    // Heading switching
    if(document.getElementById("main-heading").classList.contains("main-heading-day")){
        document.getElementById("main-heading").classList.remove("main-heading-day");
        document.getElementById("main-heading").classList.add("main-heading-night");
    } else{
        document.getElementById("main-heading").classList.remove("main-heading-night");
        document.getElementById("main-heading").classList.add("main-heading-day");
    }

}

Este enfoque es compatible con HTML5 y los navegadores modernos y, de esta manera, puede manipular las clases de manera similar a jQuery, una biblioteca de JavaScript ampliamente utilizada para manipular elementos HTML, eventos, etc.

A través de classList, puede omitir la inclusión de una biblioteca externa que reduce el PLT (Tiempo de carga de la página), que recientemente se ha convertido en una importante señal Web Vital para la calificación de SEO.

Conclusión

JavaScript obtuvo una adopción masiva debido a lo simple que hace el DOM para manipular básicamente todo en su página web, entre otras cosas.

En este tutorial, echamos un vistazo a cómo cambiar la clase de un elemento en JavaScript. *.