Saltar al contenido

CSS, de a poco

Curso de CSS

Container queries

Lección 21 de 37 · 4 min

Las media queries le preguntan a la pantalla. Las container queries le preguntan al lugar donde está el componente, así la misma pieza se acomoda sola en una columna angosta o en una ancha.

Preguntarle al contenedor

Pensá en una tarjeta que aparece en la columna principal y también en una barra lateral. Con una media query, las dos ven la misma pantalla de 1280px y se dibujan igual, aunque la barra mida 300px. Lo que la tarjeta necesita saber es cuánto mide su contenedor.

Una página de 1280px con la misma tarjeta de ruta dos veces. En la columna principal, de 640px, la tarjeta pone el perfil al lado del texto; en la barra lateral, de 300px, se apila.

Eso se resuelve en dos pasos: el padre se declara contenedor con container-type: inline-size, y sus descendientes usan una container query (@container) para aplicar reglas según el ancho del contenedor.

tarjeta.css
.panel {
container-type: inline-size;
}
@container (width >= 400px) {
.tarjeta {
flex-direction: row;
}
}

Mové el ancho del contenedor y mirá la tarjeta: desde 400px pone el perfil de la ruta al lado del texto, y desde 480px muestra la descripción. La ventana no cambia, solo el contenedor.

container-type: inline-size440px · lado a lado · título 21.2px

Ruta por la costa

3 días · 42 km

Tres días caminando entre faros y pueblos de pescadores.

tarjeta.css
.panel {
container-type: inline-size;
width: 440px;
}
.tarjeta {
display: flex;
flex-direction: column;
gap: 12px;
}
.tarjeta-titulo {
font-size: clamp(1rem, 0.5rem + 3cqi, 1.5rem);
}
.tarjeta-texto {
display: none;
}
/* activa */
@container (width >= 400px) {
.tarjeta {
flex-direction: row;
}
}
/* inactiva */
@container (width >= 480px) {
.tarjeta-texto {
display: block;
}
}
tarjeta.html
<div class="@container w-110">
<article class="flex flex-col gap-3 @min-[400px]:flex-row">
<svg class="h-32 min-w-40" viewBox="0 0 100 40" preserveAspectRatio="none">…</svg>
<div>
<h3 class="text-[clamp(1rem,0.5rem+3cqi,1.5rem)]">Ruta por la costa</h3>
<p class="hidden @min-[480px]:block">Tres días caminando entre faros y pueblos de pescadores.</p>
</div>
</article>
</div>

Una container query nunca le aplica estilos al contenedor mismo, solo a lo que tiene adentro. Y como el ancho del contenedor no puede depender de su contenido, tiene que venir de afuera: del padre, de un grid o de un width.

Contenedores con nombre y unidades cq

Sin nombre, @container consulta al contenedor más cercano. Si hay varios anidados y querés uno en particular, ponele nombre con container-name, o usá el atajo container, que lleva el nombre y el tipo separados por una barra:

sidebar.css
.sidebar {
container: sidebar / inline-size;
}
@container sidebar (width >= 400px) {
.tarjeta {
flex-direction: row;
}
}

Adentro de un contenedor también tenés sus unidades: 1cqi es el 1% de su ancho y 1cqb, el 1% de su alto. Con clamp() dan tipografía fluida, que crece con el contenedor sin pasarse de un mínimo y un máximo:

titulo.css
.tarjeta-titulo {
font-size: clamp(1rem, 0.5rem + 3cqi, 1.5rem);
}

En la demo, con 280px el título mide 8px + 8.4px = 16.4px; con 400px, 20px; y a partir de unos 533px se queda en 24px. La parte en rem hace que el título siga respetando el tamaño de letra que configuró el usuario.

El título de la tarjeta en contenedores de 280, 400 y 533px: mide 16.4, 20 y 24px. Desde unos 533px se queda en el máximo.

Tipos de contenedor y cuándo usarlos

container-type define qué se puede consultar:

  1. Solo el anchoinline-sizeEs el que vas a usar casi siempre.
  2. Ancho y altosizePero el alto tampoco puede salir del contenido, así que sin un height explícito el contenedor colapsa a 0.
  3. Por defectonormalNo permite consultar tamaños.

También existen las style queries, como @container style(--tema: oscuro), que consultan el valor de una custom property. Solo funcionan con custom properties y llegaron a los navegadores más tarde que las de tamaño, así que revisá el soporte antes de depender de ellas.

Usá media queries para lo que depende de la página o del usuario: el layout general, prefers-color-scheme o prefers-reduced-motion. Usá container queries para componentes que se reutilizan en lugares de distinto ancho. Se combinan bien: la media query arma las columnas y la container query acomoda lo que va adentro.

En Tailwind

Tailwind v4 trae container queries de fábrica, sin plugin. La clase @container declara el contenedor y las variantes que empiezan con @ consultan su ancho. La escala va en rem: @sm es 24rem (384px) y @md, 28rem (448px). Para un valor exacto, usá @min-[400px]:.

CSSTailwind
container-type: inline-size · size@container · @container-size
container: sidebar / inline-size@container/sidebar
@container (width >= 28rem) · (< 28rem)@md:* · @max-md:*
@container (width >= 400px)@min-[400px]:*
@container sidebar (width >= 28rem)@md/sidebar:*
font-size: clamp(1rem, 0.5rem + 3cqi, 1.5rem)text-[clamp(1rem,0.5rem+3cqi,1.5rem)]
tarjeta.html
<aside class="@container/sidebar">
<article class="flex flex-col gap-3 @md/sidebar:flex-row">
<img class="h-32 min-w-40 object-cover" src="…" alt="" />
<div>
<h3 class="text-[clamp(1rem,0.5rem+3cqi,1.5rem)]">Ruta por la costa</h3>
<p class="hidden @lg/sidebar:block">Tres días caminando…</p>
</div>
</article>
</aside>