CSS moderno en 2026: cosas para las que ya no necesitas JavaScript
CSS ha evolucionado enormemente. Muchas tareas que antes resolvíamos con JavaScript, librerías externas o trucos de maquetación ya forman parte de la plataforma web.
Durante muchos años el reparto de responsabilidades en una aplicación web parecía bastante claro: HTML definía la estructura, CSS se encargaba de la apariencia y JavaScript proporcionaba el comportamiento.
Era una simplificación útil, pero cada vez representa peor la realidad. Selectores capaces de reaccionar al contenido, consultas basadas en el tamaño de un componente, CSS anidado, animaciones vinculadas al scroll o elementos posicionados respecto a otros elementos de la interfaz son algunos ejemplos.
CSS ya no es simplemente el lenguaje que utilizamos para cambiar colores y márgenes. En 2026 merece la pena revisar qué significa realmente conocer CSS moderno.
El problema de aprender CSS hace unos años
Imaginemos que aprendimos desarrollo web alrededor de 2018. Probablemente nuestra caja de herramientas incluía Flexbox, Grid, Media Queries, Sass y JavaScript para manipular clases.
Con eso podíamos construir prácticamente cualquier interfaz. Y todavía podemos hacerlo. El problema es continuar desarrollando exactamente de esa manera e ignorar una parte importante de la evolución reciente del navegador.
Un ejemplo sencillo es Sass. Durante años una de las razones para utilizar un preprocesador era poder escribir estilos anidados:
Hoy podemos utilizar esa sintaxis mediante CSS Nesting nativo. No significa que Sass haya dejado de tener utilidad; significa que una de las razones históricas para introducirlo en un proyecto ha desaparecido.
1. `:has()`: CSS puede mirar dentro de un elemento
Durante años los selectores CSS funcionaban fundamentalmente en una dirección: seleccionábamos un elemento y después sus descendientes.
El problema aparecía cuando necesitábamos hacer lo contrario. Por ejemplo, aplicar un estilo diferente a una tarjeta solamente cuando contiene una imagen. Antes era habitual añadir una clase desde el servidor o inspeccionar el DOM con JavaScript.
Con `:has()` podemos expresarlo directamente:
Estamos diciendo: selecciona `.card` cuando tenga una imagen como hijo directo. También podemos reaccionar al estado de un formulario o a elementos como un descuento:
`:has()` está ampliamente disponible, pero no conviene anclarlo a selectores demasiado generales como `body` o `:root`. Mantener el contenedor y el selector interno acotados ayuda al navegador a reevaluar los cambios de forma eficiente.
2. Container Queries: componentes que conocen su propio tamaño
Las Media Queries cambiaron completamente el desarrollo responsive, pero preguntan por el tamaño del viewport. Eso funciona bien cuando diseñamos una página y peor cuando diseñamos un componente reutilizable.
Una tarjeta puede aparecer ocupando toda la pantalla, dentro de una columna, en un sidebar o en un dashboard. Su comportamiento debería depender del espacio disponible, no únicamente del tamaño de la ventana.
Aquí entran las Container Queries. Declaramos un contenedor y consultamos su tamaño:
Ahora el componente responde al tamaño de su contenedor. Esta diferencia cambia la forma de diseñar componentes para React, Angular, Vue o Web Components.
3. CSS Nesting: menos necesidad de preprocesadores
CSS Nesting permite estructurar los estilos alrededor del componente sin repetir selectores constantemente:
No hay nada incorrecto en escribir `.navigation a` y `.navigation a:hover` como reglas independientes. Sin embargo, el nesting hace más evidente la relación entre los elementos. Su sintaxis y especificidad tienen matices frente a los preprocesadores, por lo que merece la pena consultar la guía de CSS Nesting antes de migrar reglas complejas.
4. Animaciones vinculadas al scroll sin escuchar `scroll`
Un patrón clásico del frontend consiste en ejecutar una animación conforme el usuario se desplaza por la página. Durante años eso significaba un listener, cálculos de posición y actualizaciones de estilos desde JavaScript.
Las scroll-driven animations permiten vincular una animación CSS al desplazamiento:
El navegador relaciona la animación con el scroll sin un listener ejecutándose continuamente. El valor de duración distinto de cero mantiene un comportamiento consistente en navegadores que lo necesitan. JavaScript sigue siendo útil para interacciones complejas, pero una categoría completa de efectos puede resolverse de forma declarativa.
5. Anchor Positioning: tooltips y popovers con CSS
Colocar un tooltip, un menú o un selector respecto a un botón ha generado miles de líneas de JavaScript: posiciones, límites de pantalla, desplazamiento, redimensionamiento y capas superpuestas.
CSS Anchor Positioning traslada parte de esa responsabilidad al navegador. Podemos declarar un ancla y posicionar otro elemento respecto a ella:
El menú queda vinculado al botón. Esta funcionalidad es Baseline recién disponible en 2026, así que antes de adoptarla conviene revisar el público del proyecto, probar los navegadores objetivo y mantener un fallback cuando sea necesario.
6. View Transitions: transiciones entre vistas
La View Transition API permite que el navegador gestione la transición visual entre estados. En una SPA, JavaScript todavía inicia el cambio de DOM:
Pero la apariencia se define en CSS:
En navegaciones entre documentos del mismo origen también es posible activar transiciones mediante `@view-transition`. La idea importante es distinguir el comportamiento de aplicación —que puede seguir necesitando JavaScript— de una transición visual que el navegador ya conoce y puede animar. Consulta la View Transition API antes de usarla en producción.
7. CSS también empieza a tomar decisiones
Funciones como `clamp()`, `min()`, `max()` y `calc()` permiten expresar relaciones que antes requerían múltiples Media Queries o cálculos adicionales.
Son herramientas pequeñas individualmente. Juntas permiten construir sistemas responsive mucho más declarativos.
8. ¿Significa todo esto que necesitamos menos JavaScript?
En determinadas interfaces, sí. Pero CSS no sustituye a JavaScript. Seguimos necesitándolo para lógica de negocio, llamadas a API, gestión compleja de estado, manipulación de datos, autenticación, comunicaciones en tiempo real e interacción avanzada.
Lo que está cambiando es la frontera. Hay comportamientos de presentación que durante años trasladamos a JavaScript simplemente porque CSS no tenía capacidad para resolverlos. Eliminar ese JavaScript innecesario suele significar menos código, menos dependencias, menos estados que sincronizar y menos posibilidades de introducir errores.
9. El navegador se está convirtiendo en un framework más potente
Durante buena parte de la historia del frontend, las librerías evolucionaron más rápido que la plataforma. Cuando el navegador no ofrecía algo, JavaScript lo solucionaba. Necesitábamos variables y nesting: utilizábamos preprocesadores. Necesitábamos mejores selectores: utilizábamos JavaScript.
Pero la plataforma web aprende. Las soluciones útiles durante años terminan, en algunos casos, convirtiéndose en estándares. Un desarrollador frontend que solo aprende un framework corre el riesgo de mantener soluciones creadas para limitaciones que ya no existen.
10. Baseline: cómo saber si podemos utilizar una característica
CSS evoluciona tan rápidamente que es difícil saber qué podemos utilizar realmente. Una característica puede existir en la especificación sin estar disponible para todos los usuarios.
Web Platform Baseline resume la disponibilidad de funcionalidades en los navegadores principales como Limited Availability, Newly Available o Widely Available. No sustituye las pruebas ni define por sí sola la compatibilidad de un proyecto, pero ayuda a tomar decisiones sin memorizar versiones concretas de cada navegador.
Conocer CSS moderno no consiste en usar siempre lo más nuevo. Consiste en saber cuándo una característica aporta valor, qué audiencia necesita soporte y cuál es el fallback adecuado.
¿Sigue teniendo sentido aprender CSS en profundidad?
Precisamente ahora tiene más sentido. Los frameworks pueden abstraer parte del desarrollo frontend, pero todos terminan ejecutándose sobre las capacidades del navegador.
Un desarrollador que comprende bien CSS puede distinguir entre un problema que necesita JavaScript y uno que el navegador ya sabe resolver. Esa diferencia puede evitar dependencias y simplificar considerablemente una aplicación.
Conclusión
CSS está incorporando algunas de las mejoras más importantes de su historia. `:has()` permite construir relaciones entre elementos que antes eran difíciles de expresar. Container Queries hacen que los componentes respondan a su propio contexto. CSS Nesting reduce una de las razones tradicionales para utilizar preprocesadores. Las animaciones vinculadas al scroll y Anchor Positioning trasladan trabajo al navegador.
La consecuencia no es que JavaScript vaya a desaparecer. Es algo más sencillo: la plataforma web puede hacer cada vez más cosas por sí sola.
Antes de instalar otra dependencia o escribir otro listener de JavaScript, quizá deberíamos preguntarnos si el navegador ya sabe hacerlo.