DevToolBoxGRATIS
Blog

CSS Container Queries: Guía Completa 2026

13 minpor DevToolBox

CSS Container Queries representan el avance más significativo en diseño responsive desde los media queries. Los componentes responden al tamaño de su contenedor, no del viewport.

¿Qué son los Container Queries?

Los container queries aplican estilos basados en el tamaño del contenedor padre.

/* The Problem: A card component in different contexts */

/* In main content (800px wide) → horizontal layout */
/* In sidebar (300px wide) → vertical layout */
/* In footer (200px wide) → minimal layout */

/* With media queries, you cannot distinguish these contexts
   because they all exist at the same viewport width.

   With container queries, each container context triggers
   different styles automatically. */

Container Queries vs Media Queries

Los media queries solo responden al tamaño del viewport.

FeatureMedia QueriesContainer Queries
Responds toViewport sizeContainer size
ScopeGlobal (page-level)Local (component-level)
ReusabilityBreaks in different contextsWorks in any context
Use casePage layoutComponent layout
Unitsvw, vh, vmin, vmaxcqw, cqh, cqi, cqb
Browser supportUniversalAll modern browsers (2023+)

Entendiendo el Containment

Los container queries requieren containment explícito.

Tipos de containment

/* container-type values */

/* inline-size: Containment on the inline axis only (width) */
/* Most common — use this in most cases */
.card-wrapper {
  container-type: inline-size;
}

/* size: Containment on both inline and block axes (width + height) */
/* Use when you need to query both dimensions */
.widget-wrapper {
  container-type: size;
}

/* normal (default): No containment — cannot be queried */
.regular-div {
  container-type: normal; /* This is the default */
}

/* IMPORTANT: container-type: size prevents auto-height behavior.
   The element will not grow to fit its content on the block axis.
   Use inline-size unless you specifically need height queries. */

Sintaxis de Container Queries

Dos partes: definir un contenedor y escribir queries.

/* Step 1: Define a container */
.card-container {
  container-type: inline-size;
}

/* Step 2: Write container queries */
.card {
  /* Default styles (smallest) */
  display: grid;
  gap: 12px;
  padding: 16px;
}

.card__image {
  width: 100%;
  aspect-ratio: 16/9;
  border-radius: 8px;
  object-fit: cover;
}

.card__title {
  font-size: 1rem;
  font-weight: 700;
}

/* When container is at least 400px wide */
@container (min-width: 400px) {
  .card {
    grid-template-columns: 200px 1fr;
    align-items: center;
  }
  .card__title {
    font-size: 1.25rem;
  }
}

/* When container is at least 600px wide */
@container (min-width: 600px) {
  .card {
    grid-template-columns: 280px 1fr;
    gap: 24px;
    padding: 24px;
  }
  .card__title {
    font-size: 1.5rem;
  }
  .card__description {
    display: block; /* Show description only in wide containers */
  }
}

Contenedores nombrados

Nombrar contenedores para apuntar a ancestros específicos.

/* Name containers to target specific ancestors */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

.main-content {
  container-type: inline-size;
  container-name: main;
}

/* Query a specific named container */
@container sidebar (max-width: 300px) {
  .widget {
    font-size: 0.875rem;
  }
}

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

/* Without a name, @container queries the NEAREST ancestor
   with containment. Named queries skip to the named container. */

Atajo container

Combina container-type y container-name.

/* Shorthand: container: <name> / <type> */
.sidebar {
  container: sidebar / inline-size;
}

/* Equivalent to: */
.sidebar {
  container-name: sidebar;
  container-type: inline-size;
}

/* Multiple names (for querying by either name) */
.widget-area {
  container: widget-area panel / inline-size;
}

Unidades Container Query

Nuevas unidades CSS relativas al contenedor.

UnitDescriptionEquivalent
cqw1% of container widthSimilar to vw for viewport
cqh1% of container heightSimilar to vh for viewport
cqi1% of container inline sizeWidth in horizontal writing
cqb1% of container block sizeHeight in horizontal writing
cqminSmaller of cqi and cqbSimilar to vmin
cqmaxLarger of cqi and cqbSimilar to vmax
/* Fluid typography with container query units */
.card-title {
  /* Font size scales with container width */
  /* Minimum 1rem, maximum 2rem, scales at 5cqi */
  font-size: clamp(1rem, 5cqi, 2rem);
}

.card-padding {
  /* Responsive padding based on container */
  padding: clamp(12px, 4cqi, 32px);
}

.hero-text {
  /* Large text that scales with its container */
  font-size: clamp(2rem, 8cqi, 5rem);
  line-height: 1.1;
}

Ejemplos prácticos

Tarjeta responsive

Una tarjeta que se adapta al espacio disponible.

/* Responsive card component */
.card-container {
  container: card / inline-size;
}

.card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
  border-radius: 12px;
  background: var(--card-bg);
  border: 1px solid var(--border-color);
}

.card__image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 8px;
}

.card__meta {
  display: none; /* Hidden in small containers */
}

.card__actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* Medium card (400px+) — side-by-side layout */
@container card (min-width: 400px) {
  .card {
    flex-direction: row;
    align-items: flex-start;
  }
  .card__image {
    width: 180px;
    flex-shrink: 0;
    aspect-ratio: 1;
  }
  .card__meta {
    display: flex;
    gap: 12px;
    font-size: 0.875rem;
    color: var(--text-muted);
  }
}

/* Large card (700px+) — featured layout */
@container card (min-width: 700px) {
  .card {
    flex-direction: column;
    padding: 0;
    overflow: hidden;
  }
  .card__image {
    width: 100%;
    height: 300px;
    border-radius: 0;
  }
  .card__content {
    padding: 24px;
  }
  .card__title {
    font-size: 1.75rem;
  }
}

Navegación responsive

Navegación que cambia su layout según el ancho del contenedor.

/* Navigation that adapts to its container */
.nav-container {
  container: nav / inline-size;
}

.nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.nav__item {
  padding: 8px 12px;
  border-radius: 6px;
  font-size: 0.875rem;
}

.nav__item-icon {
  display: none;
}

/* Horizontal layout when container is wide enough */
@container nav (min-width: 500px) {
  .nav {
    flex-direction: row;
    gap: 8px;
  }
  .nav__item {
    white-space: nowrap;
  }
}

/* Show icons when there is more space */
@container nav (min-width: 700px) {
  .nav__item-icon {
    display: inline-flex;
    margin-right: 6px;
  }
  .nav__item {
    padding: 10px 16px;
  }
}

Elementos de grid adaptativos

Elementos que cambian según el ancho de columna.

/* Grid items that adapt to their column width */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 24px;
}

/* Each grid item is a container */
.grid__item {
  container: grid-item / inline-size;
}

.product {
  text-align: center;
  padding: 16px;
}

.product__price {
  font-size: 1.5rem;
  font-weight: 700;
}

.product__details {
  display: none;
}

@container grid-item (min-width: 350px) {
  .product {
    display: grid;
    grid-template-columns: 120px 1fr;
    text-align: left;
    gap: 16px;
  }
  .product__details {
    display: block;
  }
}

Style Container Queries

Consultar valores de estilo calculados.

/* Style container queries — query computed style values */

/* Define a container with a custom property */
.theme-container {
  container-type: normal; /* No size containment needed for style queries */
  --theme: light;
}

.theme-container.dark {
  --theme: dark;
}

/* Query the custom property value */
@container style(--theme: dark) {
  .card {
    background: #1a1a2e;
    color: #e0e0e0;
    border-color: #333;
  }
  .button {
    background: #4a90d9;
    color: white;
  }
}

@container style(--theme: light) {
  .card {
    background: #ffffff;
    color: #333;
    border-color: #e0e0e0;
  }
}

/* Practical use: component variants via CSS properties */
.alert-container {
  --variant: info;
}

@container style(--variant: error) {
  .alert {
    background: #fef2f2;
    border-left: 4px solid #ef4444;
    color: #991b1b;
  }
}

@container style(--variant: success) {
  .alert {
    background: #f0fdf4;
    border-left: 4px solid #22c55e;
    color: #166534;
  }
}

Container Queries anidados

Comportamiento responsive complejo con múltiples contenedores.

/* Nested container queries */
.page {
  container: page / inline-size;
}

.sidebar {
  container: sidebar / inline-size;
}

/* Different behavior based on multiple container sizes */
@container page (min-width: 1200px) {
  .sidebar {
    width: 350px;
  }
}

@container sidebar (max-width: 250px) {
  .sidebar-widget {
    font-size: 0.875rem;
    padding: 8px;
  }
  .sidebar-widget__title {
    font-size: 1rem;
  }
}

@container sidebar (min-width: 300px) {
  .sidebar-widget {
    padding: 16px;
  }
  .sidebar-widget__chart {
    display: block;
  }
}

Patrones de diseño

Diseño intrínseco

Combinar con CSS Grid auto-fit.

/* Intrinsic design: Grid + Container Queries */
.auto-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

.auto-grid > * {
  container-type: inline-size;
}

/* Items automatically adapt as the grid reflows */
/* No breakpoints needed — the grid column width drives the layout */
@container (min-width: 400px) {
  .feature-card {
    grid-template-columns: auto 1fr;
  }
}

@container (min-width: 500px) {
  .feature-card__description {
    font-size: 1.125rem;
  }
}

Widgets de dashboard

Widgets que se adaptan a su celda.

/* Dashboard widget pattern */
.dashboard {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
}

.dashboard__cell {
  container: widget / inline-size;
}

.widget {
  padding: 16px;
  border-radius: 12px;
  background: var(--widget-bg);
}

.widget__chart {
  height: 150px;
}

.widget__table {
  display: none; /* Hidden in small widgets */
}

@container widget (min-width: 400px) {
  .widget__chart {
    height: 200px;
  }
  .widget__stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
  }
}

@container widget (min-width: 600px) {
  .widget {
    padding: 24px;
  }
  .widget__table {
    display: table;
  }
  .widget__chart {
    height: 280px;
  }
}

Soporte del navegador

Excelente soporte en 2026.

Estrategias de fallback

Usar @supports para fallbacks.

/* Graceful fallback with @supports */
.card-container {
  /* Fallback: use media queries */
}

@supports (container-type: inline-size) {
  .card-container {
    container-type: inline-size;
  }
}

/* Fallback styles using media queries */
@media (min-width: 768px) {
  .card {
    grid-template-columns: 200px 1fr;
  }
}

/* Container query override (when supported) */
@container (min-width: 400px) {
  .card {
    grid-template-columns: 200px 1fr;
  }
}

Rendimiento

Entender el containment es importante.

  • Crea nuevo contexto de apilamiento.
  • Evitar anidamiento innecesario.
  • Usar inline-size cuando sea posible.
  • Sin pases de layout adicionales.
  • Usar contenedores nombrados.

Mejores prácticas

  1. Container queries para componentes, media queries para páginas.
  2. Empezar con inline-size.
  3. Nombrar contenedores.
  4. Usar unidades container query.
  5. Combinar con Grid y Flexbox.
  6. Diseñar de menor a mayor.
  7. Fallbacks con @supports.

Migración desde media queries

No es necesario reemplazar todos los media queries.

/* Decision Guide: Container Query vs Media Query */

/* USE CONTAINER QUERIES when:
   ✅ Component is reused in different layout contexts
   ✅ Component goes in sidebars, modals, grids, etc.
   ✅ You need component-level responsive behavior
   ✅ The component's layout depends on available space

   USE MEDIA QUERIES when:
   ✅ Changing the overall page layout
   ✅ Showing/hiding entire sections
   ✅ Adjusting global typography or spacing
   ✅ Changing navigation from desktop to mobile
   ✅ Print stylesheets

   USE BOTH when:
   ✅ Page layout switches at viewport breakpoints (media query)
   ✅ Components within the layout adapt to their containers (container query)
*/

Conclusión

CSS Container Queries cambian fundamentalmente el diseño responsive. Construya sistemas de diseño modulares y mantenibles.

FAQ

¿Diferencia entre container y media queries?

Media queries: viewport. Container queries: contenedor padre.

¿container-type en cada padre?

No, solo en los elementos contenedor.

¿Compatible con Grid/Flexbox?

Sí, perfectamente.

¿inline-size vs size?

inline-size: solo eje inline. size: ambos ejes.

𝕏 Twitterin LinkedIn
¿Fue útil?

Mantente actualizado

Recibe consejos de desarrollo y nuevas herramientas.

Sin spam. Cancela cuando quieras.

Prueba estas herramientas relacionadas

{ }CSS Minifier / Beautifier🌈CSS Gradient Generator

Artículos relacionados

Guia completa de CSS Flexbox: todas las propiedades y patrones de diseno

Domina CSS Flexbox: guia completa de propiedades de contenedor y elementos, ejemplos visuales y patrones de diseno reales.

CSS Grid Layout: tutorial completo con ejemplos practicos

Aprende CSS Grid desde cero. grid-template, repeat(), minmax(), auto-fit, areas con nombre, alineacion, subgrid y layouts responsivos sin media queries.

CSS Media Queries y breakpoints en 2025

Patrones modernos de media queries CSS y breakpoints para 2025. Container queries, consultas de preferencia y diseño responsive.