Inicio / Artículos

Envío seguro de CSS moderno: anclajes, carriles de cuadrícula, ámbito y light-dark()

Aprenda cómo el posicionamiento de anclajes, los popovers, la mampostería con carriles de cuadrícula, las transiciones de vista, light-dark() y @scope reemplazan a las bibliotecas de JavaScript, y cómo adoptar cada uno de ellos con soluciones alternativas.

Editor: REACTAPP.TOP7 min de lectura1605 palabras

Fuentes: CSS Can Already Do This. Developers Are Still Scared to Ship It.

Muchos paquetes front-end todavía incluyen una biblioteca cuya única función es determinar dónde debe colocarse una herramienta de ayuda, como Floating UI o su predecesor Popper, además de otra que organiza las tarjetas en una cuadrícula al estilo Pinterest. Los navegadores ahora pueden realizar ambas tareas de forma nativa, junto con varias otras que antes requerían JavaScript, pero pocas equipos han eliminado esas dependencias. Esta guía aborda cinco características de CSS que pueden reemplazar el código de bibliotecas comunes, explica cómo funciona cada una y muestra cómo adoptarlas sin arriesgarse a un soporte inestable en los navegadores.

Deseadas y evitadas al mismo tiempo

Las encuestas a desarrolladores reflejan bien esta tensión. En los resultados de State of CSS correspondientes a 2026, la posición del ancla fue votada como la nueva función que más entusiasmaba a los desarrolladores, superando a :has(), que ahora se utiliza tanto que ya no parece algo novedoso. La misma encuesta también preguntó qué funciones las personas evitaban intencionadamente porque aún no confiaban en su soporte en los navegadores, y la posición del ancla también encabezó esa lista. Cerrar esa brecha consiste principalmente en adoptar funciones a través de consultas de características. Las cifras de las encuestas y el estado de soporte cambian rápidamente, por lo que hay que considerarlas como un momento puntual y verificar los datos de compatibilidad actuales antes de confiar en cualquier función.

Posición del ancla en lugar de una biblioteca de tooltips

El enfoque basado en JavaScript adjunta un elemento flotante a su desencadenador midiendo ambos y recalculando la posición en cada desplazamiento o cambio de tamaño. La colocación de anclajes traslada esa relación al CSS.

A continuación, el desencadenador declara un nombre y el menú se posiciona en relación con él. La última declaración reemplaza la detección de colisiones de una biblioteca:

.trigger {
  anchor-name: --menu-trigger;
}
.menu {
  position: fixed;
  position-anchor: --menu-trigger;
  top: anchor(bottom);
  left: anchor(center);
  position-try-fallbacks: flip-block, flip-inline;
}

Cada componente tiene un papel específico:

  • anchor-name asigna a un elemento un identificador discontinuo con el que otros pueden posicionarlo.
  • position-anchor indica a un elemento posicionado qué anclaje nombrado seguir.
  • anchor() lee una coordenada, como el borde inferior o el centro horizontal del anclaje, directamente desde ese elemento.
  • position-try-fallbacks enumera las alternativas que prueba el navegador cuando el elemento podría desbordar el área de visualización; flip-block y flip-inline lo reflejan vertical u horizontalmente.
  • Combinarlo con el atributo popover

    El atributo popover, también incluido en el navegador pero ampliamente ignorado, regula el comportamiento de un menú desplegable: un botón con popovertarget activa el elemento que tenga el correspondiente, sin necesidad de scripts:

    <button popovertarget="menu">Options</button>
    <div id="menu" popover anchor-name-target="--menu-trigger">...</div>
    

    Tenga cuidado con este fragmento: anchor-name-target no es un atributo estándar de HTML, por lo que no lo copie tal cual. Conecte el popover a su ancla en CSS utilizando anchor-name y position-anchor, como se muestra anteriormente. Algunos navegadores también tratan el botón que lo invoca como un ancla implícita para un popover abierto a través de popovertarget; consulte la documentación actual antes de confiar en eso.

    Lo que popover proporciona de forma nativa es una renderización en la capa superior, por lo que el menú aparece encima de todo sin conflictos de z-index en la aplicación, se cierra automáticamente cuando el usuario hace clic fuera o presiona Escape, y cuenta con un manejo adecuado del foco al abrirse y cerrarse. No atrapa el foco como lo hace un dialog modal, así que para contenido verdaderamente modal utilice dialog en su lugar.

    Para obtener una visión más amplia de las APIs del navegador que hacen innecesarios los paquetes de npm, consulte nuestra descripción general de las APIs nativas del navegador que reemplazan a los paquetes populares.

    Masonry nativo con carriles de cuadrícula

    Dado que CSS Grid llegó a los navegadores en 2017, los diseños de tipo masonry aún requerían JavaScript, por lo que la biblioteca Masonry y paquetes similares se han instalado millones de veces. Eso está cambiando. La regla a continuación define el diseño completo:

    .gallery {
      display: grid-lanes;
      gap: 10px;
      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    }
    

    Cada tarjeta se coloca en la columna que actualmente tenga más espacio, de modo que los elementos se agrupan compactamente sin espacios irregulares. No existe un ResizeObserver, ni se vuelve a equilibrar las columnas mediante scripts cada vez que una imagen termina de cargarse. La sintaxis generó años de debate entre los fabricantes de navegadores, con Apple y Google favoreciendo enfoques diferentes, hasta que display: grid-lanes surgió como solución de compromiso.

    Según la información de compatibilidad al momento de redactar este texto, Safari lo implementó primero, mientras que Chrome y Firefox lo mantuvieron activo solo bajo flags. Eso explica por qué tan pocas páginas web lo utilizan y por qué vale la pena implementarlo ahora. Coloque grid-lanes dentro de un bloque @supports (display: grid-lanes) y deje que una cuadrícula regular sirva como alternativa.

    Transiciones de vista, con mucha precaución

    Aquí la precaución está justificada. Existe soporte para la API View Transition, pero es irregular, lo que la sitúa junto con el posicionamiento de anclajes entre las características más evitadas, y esa vacilación es razonable.

    El mecanismo básico es sencillo: envolver una actualización del DOM en document.startViewTransition() y el navegador toma instantáneas de los estados antiguos y nuevos para hacer un fundido entre ellos, sin necesidad de bibliotecas de animación ni de llevar un registro manual antes y después. Los pseudo-elementos a continuación controlan esa transición por defecto, acortándola aquí a 0.3 segundos:

    ::view-transition-old(root),
    ::view-transition-new(root) {
      animation-duration: 0.3s;
    }
    

    Hoy en día, su uso confiable se da como mejora progresiva. Un navegador que no cuenta con la API simplemente pasa al nuevo estado, por lo que nada falla. Eso lo hace seguro para momentos no críticos como cambiar de página o reorganizar una lista. En los scripts, verifique que document.startViewTransition exista antes de llamarlo, y recurre a aplicar la actualización directamente si no está disponible.

    Una paleta para modo claro y oscuro con light-dark()

    Un modo oscuro típico mantiene dos sistemas de colores completos, uno dentro de una consulta de medios prefers-color-scheme: dark y otro fuera. La función light-dark() combina cada par en una sola declaración.

    El fragmento a continuación primero configura el documento para ambos esquemas mediante color-scheme, algo necesario para que light-dark() funcione, y luego asigna los valores claros y oscuros para cada propiedad uno al lado del otro:

    :root {
      color-scheme: light dark;
    }
    
    body {
      background: light-dark(#ffffff, #1a1a1a);
      color: light-dark(#111111, #eeeeee);
    }
    

    Una vez que se establece color-scheme, cada llamada a light-dark() devuelve el valor adecuado según las preferencias del sistema del usuario, y ya no es necesario duplicar consultas de medios en la hoja de estilos. Para conocer otras formas de implementar temas, consulte nuestra comparación de técnicas de modo oscuro.

    Contener estilos con @scope

    Gran parte de la motivación detrás de CSS-in-JS o de los nombres estrictos BEM radica en la fuga de especificidad: una regla .card destinada a un componente también estiliza un .card no relacionado anidado más profundamente en el marcado de otra persona. @scope limita los estilos a un subárbol de forma nativa.

    En la regla a continuación, los estilos del párrafo se aplican dentro de .card pero cesan en cualquier elemento .card-nested:

    @scope (.card) to (.card-nested) {
      p {
        color: var(--card-text);
      }
    }
    

    El primer selector establece la raíz del ámbito. La cláusula to define un límite inferior, dejando un espacio donde un componente anidado puede gestionar sus propios estilos en lugar de heredarlos del padre. Todo esto no requiere paso de compilación, nombres de clases generados ni JavaScript en tiempo de ejecución. No reemplazará todo lo que hace CSS-in-JS, como los estilos calculados a partir de las propiedades del componente, pero elimina una de las principales razones por las que los equipos lo adoptan.

    El navegador es el ecosistema

    Todas estas cinco funcionalidades ya están disponibles al menos en un navegador real hoy en día, y ninguna de ellas depende de React, un plugin de bundler ni una versión de framework. La distancia entre lo que puede hacer CSS y lo que implementan los equipos se debe en gran medida a la costumbre: durante una década, resolver un problema de interfaz ha significado instalar un paquete.

    Elija un lugar en su proyecto donde se utilice una solución temporal con JavaScript para uno de estos problemas, cámbielo detrás de @supports y vea qué deja de funcionar. Por lo general, será menos de lo que espera.

    Preguntas frecuentes

    ¿Está listo el posicionamiento de anclajes para producción?

    Ya se ha lanzado y puede usarse hoy mismo detrás de una comprobación con @supports. Su presencia en la lista de opciones a evitar se debe a la precaución ante una implementación desigual entre los navegadores, no a que sea una función defectuosa. Combinarlo con una solución alternativa, como un posicionamiento estático más simple, constituye el nivel adecuado de precaución.

    ¿Todavía se necesita una biblioteca de masonry?

    Para un proyecto nuevo, probablemente no, siempre y cuando display: grid-lanes esté dentro de un bloque @supports con una cuadrícula normal como solución alternativa. En el caso de un diseño ya en producción con una matriz estricta de compatibilidad entre navegadores, mantenga la biblioteca por más tiempo.

    ¿Qué función debería adoptar primero?

    light-dark(). Se trata de un cambio de una sola línea por cada valor de color, contaba con el mayor soporte de las cinco en el momento de redactar este texto, y elimina un bloque de CSS duplicado para el modo oscuro sin riesgo alguno para el diseño.

    Puntos clave

    • Trate cada función como una mejora progresiva: comportamiento nativo donde esté soportado, o una solución existente en otro lugar.
    • La posición del ancla junto con popover cubre la mayoría de las necesidades relacionadas con tooltips y menús desplegables, pero conecte el ancla en CSS y utilice dialog cuando necesite un modal real.
    • grid-lanes y las transiciones de vista son los menos establecidos; controle su uso con @supports o una verificación en tiempo de ejecución.
    • light-dark() y @scope eliminan el código de inmediato y conllevan el menor riesgo.

    Lecturas relacionadas

  • Un flujo de trabajo asistido por IA para enviar un sitio web pequeño a Cloudflare — Un flujo de trabajo reutilizable y plantillas de instrucciones para diseñar, iterar y desplegar un sitio pequeño con la ayuda de un asistente de programación por IA, GitHub y la versión gratuita de Cloudflare.
  • Sustituyendo librerías de tooltip con la API Popover y el posicionamiento ancla CSS — Por qué las tooltips necesitaban Popper y Floating UI, qué función nativa resuelve ahora el apilamiento, posicionamiento y cierre, y cuándo aún vale la pena usar una librería de JavaScript.