classList API: Guía Completa para Manipulación de Clases CSS
Domina la API moderna para manipular clases CSS. Aprende add, remove, toggle, casos de uso reales, transiciones CSS y mejores prácticas.
TL;DR - Resumen rápido
- classList es un DOMTokenList: métodos add(), remove(), toggle(), contains(), replace().
- toggle() acepta segundo parámetro booleano para forzar add/remove condicionalmente.
- DOMTokenList es iterable: usa forEach(), length, item(index) para recorrer clases.
- Mucho más seguro que className: no borra clases accidentalmente, maneja espacios correctamente.
- Patrón común: classList + CSS transitions para animaciones suaves sin JavaScript adicional.
- Performance: classList es más rápido que setAttribute('class') para cambios individuales.
La API Moderna para Clases CSS
La forma profesional de manipular estilos en JavaScript es añadiendo y quitando clases CSS predefinidas, no modificando style directamente. Antes de classList, esto requería manipulación manual de strings propensa a errores: element.className += ' nueva-clase' con riesgo de olvidar espacios y borrar clases existentes accidentalmente.
La API classList resuelve este problema completamente. Es un objeto DOMTokenList que representa las clases del elemento como una colección inteligente con métodos dedicados. No más concatenación de strings, no más bugs de espacios en blanco, no más verificaciones manuales de duplicados.
Métodos Principales: add, remove, replace, contains
La propiedad classList es un objeto DOMTokenList que representa las clases CSS del elemento como una colección inteligente. A diferencia de className (que es un string), classList ofrece métodos dedicados para cada operación.
Características clave de estos métodos:
- <strong>add() acepta múltiples argumentos</strong>: Puedes agregar varias clases a la vez con add('clase1', 'clase2', 'clase3').
- <strong>add() ignora duplicados</strong>: Si la clase ya existe, no la agrega de nuevo ni causa error.
- <strong>remove() no da error si no existe</strong>: Puedes remover una clase que no está presente sin problemas.
- <strong>contains() es rápido</strong>: Verifica existencia en tiempo constante O(1), ideal para condicionales.
- <strong>replace() es atómico</strong>: Intercambia una clase por otra en un solo paso, sin estado intermedio.
Performance: contains() vs querySelector()
element.classList.contains('active') es muchísimo más rápido que element.matches('.active') porque no necesita parsear un selector CSS completo, solo busca en la lista de clases.
toggle(): El Método Más Versátil
El método toggle() es probablemente el más útil de classList para interfaces interactivas. Su comportamiento es simple: si la clase existe, la elimina; si no existe, la agrega. Devuelve true si la clase fue agregada, false si fue eliminada.
El segundo parámetro opcional de toggle(className, force) es extremadamente poderoso: te permite controlar explícitamente si la clase debe agregarse o eliminarse basándote en una condición booleana. Esto elimina la necesidad de escribir if/else manualmente y hace el código más declarativo.
Patrón: toggle() con Condición
En lugar de if (isActive) el.classList.add('active'); else el.classList.remove('active');, usa simplemente el.classList.toggle('active', isActive). Más limpio y menos propenso a errores.
DOMTokenList: Iteración y Propiedades
classList no es un Array, sino un objeto DOMTokenList. Sin embargo, es iterable y tiene propiedades útiles: length (cantidad de clases), item(index) (acceder por índice), y forEach() para iteración. Esto te permite procesar todas las clases de un elemento programáticamente.
Aunque raramente necesitas iterar sobre classList en aplicaciones normales, estas capacidades son útiles para herramientas de debugging, librerías que analizan el DOM, o sistemas de componentes que necesitan inspeccionar clases dinámicamente.
classList vs className: ¿Por qué Evitar el Antiguo?
La propiedad className (parte de DOM Level 0) trata todas las clases como un solo string. Para agregar una clase sin borrar las existentes, necesitas concatenación manual con espacios correctos. Para eliminar una clase, necesitas split, filter, join. Para verificar existencia, necesitas expresiones regulares. Todo esto es frágil y propenso a bugs.
classList elimina completamente esta categoría de errores. Los métodos manejan espacios automáticamente, ignoran duplicados, y no requieren verificaciones manuales. Solo usa className si necesitas reemplazar TODAS las clases de golpe (ej: element.className = 'reset').
Bug Común: Olvidar el Espacio
element.className += 'nueva' (sin espacio) resulta en class="viejanNueva" (pegadas). Con classList este bug es imposible: classList.add('nueva') siempre funciona correctamente.
Casos de Uso Reales: Componentes UI
classList brilla en componentes UI interactivos donde necesitas cambiar clases dinámicamente en respuesta a acciones del usuario. Aquí los patrones más comunes en aplicaciones reales:
Sistema de Tabs
Un sistema de tabs requiere activar una tab y desactivar las demás. classList hace esto trivial combinando remove en todas las tabs y add en la activa.
Dropdown Menu
Dropdowns usan toggle para abrir/cerrar, y a menudo necesitan detectar clics fuera para cerrarse automáticamente. classList con event delegation hace esto eficiente.
Theme Switcher Completo
Un theme switcher profesional debe persistir la preferencia en localStorage, sincronizarse con la preferencia del sistema, y aplicar el tema inmediatamente sin flicker.
classList + Transiciones CSS: Animaciones Sin JavaScript
Un patrón poderoso es combinar classList con transiciones CSS. JavaScript solo agrega/quita clases; CSS maneja toda la animación. Esto es más performante que animar con JavaScript y permite usar CSS para definir la duración, easing y propiedades animadas.
Este patrón es fundamental en aplicaciones modernas: modales que aparecen con fade-in, notificaciones que se deslizan, menús que se expanden. JavaScript controla cuándo ocurre la animación (toggle de clase), CSS controla cómo se ve (transition o animation).
Ventaja de Performance: CSS vs JS
Las transiciones CSS son más eficientes que animar con JavaScript (requestAnimationFrame) porque el navegador puede optimizarlas internamente, usar aceleración por hardware (GPU), y evitar recalcular layout en cada frame.
Performance y Mejores Prácticas
classList es generalmente rápido, pero hay consideraciones de rendimiento importantes cuando trabajas con muchos elementos o cambios frecuentes de clases.
- <strong>classList es más rápido que setAttribute</strong>: Para cambios individuales de clases, classList.add() es más rápido que setAttribute('class', ...).
- <strong>Batch de operaciones</strong>: Si necesitas agregar múltiples clases, usa add('a', 'b', 'c') en lugar de tres llamadas separadas.
- <strong>Evita reflows innecesarios</strong>: Cambiar clases que afectan el layout (display, position) causa reflow. Agrupa cambios cuando sea posible.
- <strong>Usa toggle con fuerza</strong>: toggle('clase', condicion) es más limpio y ligeramente más rápido que if/else manual.
Errores Comunes con classList
Aunque classList es más seguro que className, todavía hay errores comunes que cometen los desarrolladores, especialmente al empezar:
El error más común es intentar agregar múltiples clases con espacios en un solo string (add('clase1 clase2')), que agrega literalmente una clase con espacio en el nombre. Siempre usa argumentos separados o arrays con spread.
Resumen: classList API
Conceptos principales:
- •classList es un DOMTokenList con métodos dedicados para cada operación.
- •Métodos: add(), remove(), toggle(), contains(), replace().
- •toggle(className, force) acepta booleano para forzar add/remove.
- •DOMTokenList es iterable: length, item(index), forEach().
- •className manipula string completo; classList manipula clases individuales.
- •Patrón común: classList + CSS transitions para animaciones performantes.
Mejores prácticas:
- •Usa classList siempre; solo usa className para reemplazar todas las clases.
- •add() acepta múltiples argumentos: add('a', 'b', 'c').
- •toggle() con condición es más limpio que if/else manual.
- •Combina con CSS transitions: JS controla cuándo, CSS controla cómo.
- •Performance: classList.add() es más rápido que setAttribute('class').
- •Evita add('clase1 clase2') con espacio; usa add('clase1', 'clase2').