Cargando...

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:

Turn a rail into a size container

css
.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 reacts to its parent width

css
.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:

Target a named containment context

css
@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):

Type that tracks the container

css
.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:

Sidebar rail and main stage share one card

css
.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é:

Viewport for the page, container for the card

css
@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ú

  1. Añade container-type: inline-size a un wrapper de la tarjeta; confirma en DevTools el contexto de contención.
  2. Escribe @container (min-width: 24rem) para pasar de apilado a dos columnas.
  3. Pon container-name: panel y apunta con @container panel (min-width: 30rem).
  4. Tamaño de título con cqi y redimensiona solo el padre (no la ventana).
  5. Deja un @media en el shell de página; no dupliques esa lógica dentro de la tarjeta.

Errores frecuentes

  • Escribir @container sin container-type en 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 menudo inline-size); container-name opcional para claridad
  • @container (min-width: …) / @container name (…) para reestilizar descendientes
  • cqi / cqw cuando las longitudes deben seguir al contenedor
  • Siguiente en Modern Toolkit: feature queries (@supports) — estilos según capacidad del navegador

🧠 Pon a Prueba tu Conocimiento

Listo para Empezar

Pon a Prueba tu Conocimiento

Ponte a prueba con este cuestionario interactivo y descubre qué tan bien entiendes el tema

❓
6
Preguntas
🎯
70%
Para Aprobar
♾️
∞
Tiempo
🔄
∞
Intentos

📝 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