Container queries CSS
Nesting mantuvo los selectores del componente juntos. Las media queries siguen mirando el viewport. Las container queries responden otra pregunta: ¿qué ancho tiene esta caja padre? Así la misma tarjeta de producto queda compacta en un rail estrecho y se abre en la columna principal — aunque la ventana del navegador no haya cambiado.
Por qué el viewport no basta
En muchos diseños la misma componente va en huecos desiguales: un rail lateral de 16rem y un área principal flexible. Ambos comparten el ancho del viewport, así que @media (min-width: …) se dispara igual en los dos. Necesitas estilos que dependan del contenedor que envuelve la tarjeta, no de toda la pantalla.
Crear un contexto de contención
Elige el padre que debe informar su tamaño. Pon container-type — normalmente inline-size para consultar el tamaño en línea del padre (ancho en escritura horizontal) sin forzar contención de tamaño en ambos ejes:
.rail {
container-type: inline-size;
container-name: rail;
width: 16rem;
padding: 1rem;
background: #f8fafc;
}
.stage {
container-type: inline-size;
container-name: stage;
flex: 1;
min-width: 0;
padding: 1.25rem;
}
Sin container-type, @container no tiene nada fiable que medir. container-name es opcional pero muy útil cuando varios ancestros son contenedores — apuntas a uno por nombre.
Consultar el contenedor con @container
Tras preparar el padre, envuelve reglas en @container con una condición de tamaño. Los descendientes reaccionan cuando esa caja cumple — no cuando cambia solo el viewport:
.product-card {
display: grid;
gap: 0.75rem;
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
background: #fff;
}
.product-card .media {
aspect-ratio: 16 / 10;
border-radius: 0.5rem;
background: #cbd5e1;
}
.product-card .meta {
font-size: 0.875rem;
color: #64748b;
}
@container (min-width: 28rem) {
.product-card {
grid-template-columns: 10rem 1fr;
align-items: center;
}
.product-card .title {
font-size: 1.25rem;
}
}
Si .product-card vive en un .rail estrecho, se queda en una columna. El mismo HTML en un .stage ancho activa dos columnas — mismo markup, mismo viewport, distinto ancho de contenedor.
Contenedores con nombre
Si contenedores anidados confunden qué caja se consulta, indica el nombre tras @container:
@container stage (min-width: 36rem) {
.product-card {
grid-template-columns: 12rem 1fr auto;
gap: 1.25rem;
}
.product-card .buy {
justify-self: end;
}
}
@container rail (max-width: 18rem) {
.product-card .meta {
display: none;
}
}
@container stage (…) solo atiende al ancestro llamado stage. Las reglas ajustadas del rail no chocan con las amplias del stage cuando ambos envuelven markup relacionado.
Unidades de container query
Con contexto de contención, longitudes como cqi (1 % del tamaño en línea del contenedor de consulta) y cqw (1 % de su ancho) hacen que tipografía y espaciado sigan al padre, no al viewport (vi / vw):
.product-card .title {
font-size: clamp(1rem, 0.85rem + 2.5cqi, 1.5rem);
}
.product-card {
padding: clamp(0.75rem, 2.5cqi, 1.5rem);
}
Combínalas con var() y clamp() de lecciones anteriores del Modern Toolkit. Las unidades de contenedor miden el contexto usado en la consulta — ideales para widgets reutilizables.
Contenedor frente a media: quién hace qué
📊 Container queries vs media queries
| Pregunta que haces | Mejor opción | Herramienta habitual |
|---|---|---|
| ¿Qué ancho tiene el viewport del navegador? | Shell de página, nav, página multicolumna | @media (min-width: …) |
| ¿Qué ancho tiene este padre alrededor del componente? | Tarjetas, widgets, embeds en huecos desiguales | @container (min-width: …) tras container-type |
| ¿Necesito ambas? | A menudo sí | MQ para la página; CQ para el componente en el hueco |
Dos huecos, un componente
Un boceto pequeño muestra la ganancia — dos contenedores, una clase de tarjeta:
.page {
display: flex;
gap: 1rem;
align-items: start;
}
.rail {
container-type: inline-size;
container-name: rail;
width: 16rem;
}
.stage {
container-type: inline-size;
container-name: stage;
flex: 1;
min-width: 0;
}
/* Same .product-card class in both slots — @container rules above decide layout */
No hace falta bifurcar .product-card--sidebar y .product-card--main solo por el ancho del hueco. El hueco informa su tamaño; la tarjeta escucha.
Combinar media de página con contenedores del componente
Reserva las consultas de viewport para decisiones de página (plegar la nav, una sola columna en el shell). Usa container queries para decisiones de componente en el hueco que la página le dé:
@media (max-width: 40rem) {
.page {
flex-direction: column;
}
.rail {
width: auto;
}
}
@container (min-width: 28rem) {
.product-card {
grid-template-columns: 10rem 1fr;
}
}
En un móvil pequeño la página se apila; en un escritorio ancho el rail puede seguir estrecho y el stage ancho — solo las container queries expresan bien esa diferencia.
Pruébalo tú
- Añade
container-type: inline-sizea un wrapper de la tarjeta; confirma en DevTools el contexto de contención. - Escribe
@container (min-width: 24rem)para pasar de apilado a dos columnas. - Pon
container-name: panely apunta con@container panel (min-width: 30rem). - Tamaño de título con
cqiy redimensiona solo el padre (no la ventana). - Deja un
@mediaen el shell de página; no dupliques esa lógica dentro de la tarjeta.
Errores frecuentes
- Escribir
@containersincontainer-typeen un ancestro — nada útil que medir - Sustituir todas las media queries por container queries — el shell sigue siendo de
@media - Anidar tres contenedores sin saber qué ancho manda — nómbralos y apunta con claridad
- Copiar breakpoints de viewport (
48rem) a ciegas en cada widget — afina al hueco, no al catálogo de dispositivos - Mezclar nesting (
&, selectores anidados) con contención — nesting ordena selectores; container queries miden cajas
Resumen
- Las container queries estilan según el tamaño del padre, no solo el viewport
container-type(a menudoinline-size);container-nameopcional para claridad@container (min-width: …)/@container name (…)para reestilizar descendientescqi/cqwcuando las longitudes deben seguir al contenedor- Siguiente en Modern Toolkit: feature queries (
@supports) — estilos según capacidad del navegador
🧠 Pon a Prueba tu Conocimiento
Pon a Prueba tu Conocimiento
Ponte a prueba con este cuestionario interactivo y descubre qué tan bien entiendes el tema
📝 Instrucciones
- Lee cada pregunta cuidadosamente
- Selecciona la mejor respuesta para cada pregunta
- Puedes repetir el quiz tantas veces como quieras
- Tu progreso se mostrará en la parte superior