Las consultas sobre contenedores comienzan a llegar a navegadores estables mientras se actualiza polyfill

¡Llegaron las consultas de contenedores!

Tenemos una noticia emocionante: ¡una de las funciones para desarrolladores más solicitadas ha empezado a llegar a los navegadores web! A partir de Chromium 105 y Safari 16, ahora puedes crear consultas de contenedor basadas en el tamaño y usar valores de unidades de consulta de contenedor en estos navegadores. Para que sea aún más fácil usar las consultas de contenedores basadas en el tamaño y las unidades cq, el equipo de Aurora en Chrome trabajó arduamente para actualizar el polyfill de consultas de contenedores y admitir más navegadores y casos de uso, de modo que puedas usar esta función potente con confianza hoy mismo.

¿Qué son las consultas de contenedores?

Las consultas de contenedores son una función de CSS que te permite escribir lógica de diseño orientada a los componentes de un elemento superior para definir el estilo de los elementos secundarios. Para crear un diseño responsivo realmente basado en componentes, consulta el tamaño de un elemento superior. Esta es una información mucho más detallada y útil que las consultas de medios, que solo proporcionan información de tamaño sobre el viewport.

ALT_TEXT_HERE

Con las consultas de contenedor, puedes escribir componentes reutilizables que pueden aparecer de forma diferente según dónde se encuentren en la página. Esto los hace mucho más resistentes y responsivos en todas las páginas y plantillas.

Usa consultas de contenedores

Supongamos que tienes el siguiente código HTML:

<!-- card parent -->
<div class=”card-parent”>
  <div class=”card>
     <!-- card contents -->
      …
  </div>
</div>

Para usar una consulta de contenedor, primero debes establecer la contención en el elemento superior del que deseas hacer un seguimiento. Para ello, configura la propiedad container-type o usa el atajo container para establecer el tipo y el nombre del contenedor al mismo tiempo.

.card-parent {
  /* query the inline-direction size of this parent */
  container-type: inline-size;
}

Ahora, puedes usar la regla @container para establecer estilos en función del elemento superior más cercano. Para un diseño como la imagen anterior, en el que una tarjeta puede ir de una columna a dos, escribe algo como lo siguiente:

@container (min-width: 300px) {
  .card {
    /* styles to apply when the card container (.card-parent in this case) is >= 300px */
    /* I.e. shift from 1-column to 2-column layout: */
    grid-template-columns: 1fr 1fr;
  }
}

Para que sea más ordenado y explícito, asigna un nombre al contenedor del elemento superior:

.card-parent {
  container-type: inline-size;
  /* set name here, or write this in one line using the container shorthand */
  container-name: card-container;
}

Luego, vuelve a escribir el código anterior de la siguiente manera:

@container card-container (min-width: 300px) {
  .card {
    grid-template-columns: 1fr 1fr;
  }
}

Unidades de consulta de contenedores

Para que las consultas de contenedores sean aún más útiles, también puedes usar valores de unidad basados en contenedores. En la siguiente tabla, se muestran los posibles valores de unidad de contenedor y cómo se corresponden con el tamaño de un contenedor:

Unidaden relación con
cqw1% del ancho de un contenedor de consulta
cqh1% de la altura de un contenedor de consulta
cqiEl 1% del tamaño intercalado de un contenedor de consulta
cqbEl 1% del tamaño del bloque de un contenedor de consulta
cqminEl valor más bajo de cqi o cqb
cqmaxEl valor más alto de cqi o cqb

Un ejemplo de cómo usarías unidades basadas en contenedores es la tipografía responsiva. Las unidades basadas en viewport (como vh, vb, vw y vi) se pueden usar para ajustar el tamaño de cualquier elemento en la pantalla.

.card h2 {
  font-size: 15cqi;
}

Este código hará que el tamaño de la fuente sea el 15% del tamaño intercalado del contenedor, lo que significa que aumentará a medida que aumente el tamaño intercalado (ancho) o disminuirá a medida que disminuya. Para llevar esto aún más lejos, usa la función clamp() para darle a tu tipografía un límite de tamaño mínimo y máximo, y ajusta su tamaño de forma responsiva según el tamaño del contenedor:

.card h2 {
  font-size: clamp(1.5rem, 15cqi, 3rem);
}

Ahora el encabezado nunca será mayor que 3rem ni menor que .5rem, pero ocupará el 15% del tamaño intercalado del contenedor en cualquier lugar.

Esta demostración va un paso más allá y actualiza las tarjetas más anchas para que tengan un rango de tamaño más pequeño, ya que se presentan en una vista de 2 columnas.

El polyfill de la consulta del contenedor

Dado que las consultas de contenedores son una función tan poderosa, queremos que te sientas cómodo para incorporarlas en tus proyectos. Además, queremos que sepas que la compatibilidad con los navegadores es una parte importante de ello. Por esta razón, hemos estado trabajando para mejorar el Polyfill de consulta de contenedores. Este polyfill tiene compatibilidad general en los siguientes navegadores:

  • Firefox 69 y versiones posteriores
  • Chrome 79 y versiones posteriores
  • Edge 79 y versiones posteriores
  • Safari 13.4 y versiones posteriores

Tiene un tamaño inferior a 9 KB cuando se comprime y usa RenameObserver con MutationObserver para admitir la sintaxis completa de la consulta @container que está disponible actualmente en navegadores estables:

  • Consultas discretas (width: 300px y min-width: 300px).
  • Consultas por rango (200px < width < 400px y width < 400px).
  • Unidades de longitud relativa del contenedor (cqw, cqh, cqi, cqb, cqmin ycqmax) en propiedades y fotogramas clave

Usa el polyfill de consulta de contenedor

Para usar el polyfill, agrega la siguiente etiqueta de secuencia de comandos al encabezado del documento:

<script type="module">
  if (!("container" in document.documentElement.style)) {
    import("https://unpkg.com/container-query-polyfill@^0.2.0");
  }
</script>

También puedes usar un servicio para entregar condicionalmente el polyfill en función de User-Agent o autoalojarlo en tu propio origen.

Para obtener la mejor experiencia del usuario, se recomienda que, inicialmente, solo uses el polyfill para el contenido de la mitad inferior de la página y las búsquedas de @supports para reemplazarlo temporalmente por un indicador de carga hasta que el polyfill esté listo para mostrarlo:

@supports not (container-type: inline-size) {
  .container,
  footer {
    display: none;
  }

  .loader {
    display: flex;
  }
}

En redes y dispositivos lo suficientemente rápidos, o en dispositivos que admiten consultas de contenedores de forma nativa, este indicador de carga nunca se mostrará.

Nuevas funciones de Polyfill

El polyfill actualizado admite lo siguiente:

  • Reglas @container anidadas
  • Se admite la anidación de reglas @container en consultas @supports y @media, y viceversa.
  • El CSS condicional, como @supports (container-type: inline-size), pasará después de que se cargue el polyfill.
  • Compatibilidad total con la sintaxis CSS (ya no hay problemas para colocar comentarios en cualquier lugar que sean válidos sintácticamente).
  • Modos de escritura vertical (a través de writing-mode).
  • Las unidades relativas de contenedor (cqw, cqh, etc.) son compatibles con las condiciones de consulta, las declaraciones de propiedades y los fotogramas clave de animación. rem y em son compatibles con las condiciones de consulta.
  • Sintaxis de consulta de contenedor expandida:
    • Sintaxis de rango (por ejemplo, (200px < width < 400px)).
    • Consultas de igualdad (por ejemplo, (width = 200px)).
  • Elementos pseudo como ::before y::after
  • Los navegadores sin :is(...)/:where(...) son compatibles mediante una solución alternativa opcional.
  • Las consultas de funciones orientation y aspect-ratio
  • Filtrar correctamente las consultas en función de las funciones (por ejemplo, no se permite consultar height en container: inline-size con un modo de escritura horizontal).
  • Mutación del DOM (por ejemplo, elementos <style> y <link> que se quitan durante el tiempo de ejecución)

Limitaciones y advertencias de Polyfill

Si usas el polyfill de consulta de contenedor, faltan algunas funciones que debes tener en cuenta:

  • Aún no se admite Shadow DOM.
  • Las unidades relativas de contenedor (por ejemplo, cqw y cqh) no son compatibles con las condiciones de consulta @media.
    • Safari: Las unidades relativas de contenedores no son compatibles con los fotogramas clave de animación anteriores a la versión 15.4.
  • calc(), min(), max() y otras funciones matemáticas aún no se admiten en las condiciones de consulta.
  • Este polyfill solo funciona con CSS intercalado y del mismo origen. No se admiten los diseños de página de origen cruzado ni los diseños de página en iframes (a menos que se cargue un polyfill de forma manual).
  • La contención de layout y style requiere compatibilidad con el navegador subyacente:
    • Safari 15.4 y versiones posteriores
    • Por el momento, Firefox no admite el aislamiento de estilo, pero está trabajando en ello.

Advertencias

  • Para evitar afectar el FID y el CLS, el polyfill no garantiza cuándo se producirá el primer diseño, incluso si se carga de forma síncrona, excepto que intentará evitar retrasar de manera injustificada el LCP. En otras palabras, nunca debes confiar en él para la primera pintura.
  • Genera ResizeObserver Loop Errors. El polyfill original también lo hace, pero vale la pena mencionarlo. Esto ocurre porque es probable que el tamaño del bloque de una container-type: inline-size cambie después de evaluar una búsqueda, pero ResizeObserver no tiene forma de indicarle que no nos preocupan los cambios de tamaño del bloque.
  • Este polyfill se probó con las Pruebas de la plataforma web y alcanzó el 70% de aprobación, ya que ciertas funciones, como las APIs de JavaScript, no tienen polyfill, por lo que la tasa de aprobación es intencionalmente cercana al 70%.
  • La solución alternativa de :where() es obligatoria para el 2.23% de los usuarios de navegadores anteriores a los siguientes:
    • Safari 14
    • Chromium 88
    • Edge 88
    • Samsung Internet 15
    • Firefox 78