CSS

CSS

Tutorial CSS: Container queries

Aprende container queries en CSS para crear componentes adaptables según el tamaño del contenedor, mejorando el diseño responsive y el rendimiento.

Aprende CSS y certifícate

Diferencias entre container queries y media queries

Las media queries han sido durante años la herramienta principal para crear diseños adaptables en CSS, permitiéndonos aplicar estilos según las características del dispositivo o la ventana del navegador. Sin embargo, con la llegada de las container queries, tenemos una nueva y potente forma de crear componentes verdaderamente adaptables.

Enfoque de adaptabilidad

La diferencia más fundamental entre ambas técnicas radica en su punto de referencia:

  • Media queries: Se basan en las dimensiones de la ventana del navegador (viewport) o características del dispositivo.
  • Container queries: Se basan en el tamaño del elemento contenedor específico.

Esta distinción es crucial porque cambia completamente el paradigma de diseño responsive:

/* Media query: se activa cuando la ventana del navegador es menor a 600px */
@media (max-width: 600px) {
  .card {
    flex-direction: column;
  }
}

/* Container query: se activa cuando el contenedor es menor a 400px */
@container (max-width: 400px) {
  .card {
    flex-direction: column;
  }
}

Componentes reutilizables

Las container queries permiten crear componentes verdaderamente autónomos que se adaptan a su contexto de uso, no al dispositivo:

  • Con media queries, un componente siempre se comporta igual en un mismo tamaño de pantalla, independientemente de dónde se coloque.
  • Con container queries, el mismo componente puede mostrarse de diferentes formas en la misma pantalla, dependiendo del espacio disponible en su contenedor.

Por ejemplo, imagina una tarjeta de producto que puede aparecer en diferentes secciones de una página:

/* El componente se adapta según su contenedor, no según la pantalla */
.product-card {
  display: grid;
  gap: 1rem;
}

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

@container (max-width: 299px) {
  .product-card {
    grid-template-columns: 1fr;
  }
}

Contexto de aplicación

Otra diferencia importante está en el ámbito de aplicación de los estilos:

  • Media queries: Afectan potencialmente a toda la página, lo que puede generar efectos cascada no deseados.
  • Container queries: Limitan sus efectos al contenedor específico y sus descendientes, proporcionando un aislamiento más efectivo.

Anidamiento y composición

Las container queries brillan especialmente en diseños complejos con componentes anidados:

/* Contenedor principal */
.layout {
  container-type: inline-size;
}

/* Componente que se adapta a su contenedor */
@container (min-width: 700px) {
  .sidebar {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
  }
}

/* Componente anidado que se adapta a su propio contenedor */
.widget {
  container-type: inline-size;
}

@container (max-width: 200px) {
  .widget-content {
    font-size: 0.8rem;
  }
}

En este ejemplo, tenemos componentes que se adaptan independientemente según sus propios contenedores, algo difícil de lograr con media queries.

Rendimiento y especificidad

En términos de rendimiento:

  • Media queries: Se evalúan constantemente durante el redimensionamiento de la ventana.
  • Container queries: Se evalúan cuando cambia el tamaño del contenedor específico.

Esto puede resultar en un mejor rendimiento en páginas complejas, ya que solo se recalculan los estilos de los contenedores afectados.

Casos de uso ideales

Cada técnica tiene sus escenarios óptimos de aplicación:

  • Media queries: Ideales para cambios a nivel de layout general, como reorganizar secciones principales, ocultar/mostrar menús de navegación o ajustar márgenes globales.
/* Cambio de layout general con media queries */
@media (max-width: 768px) {
  .main-layout {
    grid-template-columns: 1fr;
  }
  
  .desktop-menu {
    display: none;
  }
  
  .mobile-menu {
    display: block;
  }
}
  • Container queries: Perfectas para componentes reutilizables que deben adaptarse a diferentes contextos dentro de la misma página.
/* Adaptación de componente según su contenedor */
.card-container {
  container-type: inline-size;
}

@container (min-width: 350px) {
  .card-title {
    font-size: 1.5rem;
  }
  
  .card-image {
    float: left;
    width: 40%;
  }
}

Compatibilidad y adopción

Una consideración práctica importante es la compatibilidad con navegadores:

  • Media queries: Soporte universal en todos los navegadores modernos.
  • Container queries: Característica más reciente con soporte creciente pero no universal.

Esta diferencia puede influir en la decisión de qué técnica utilizar según los requisitos del proyecto y su público objetivo.

Sintaxis y estructura

La sintaxis también difiere significativamente:

  • Media queries: Utilizan @media seguido de condiciones sobre el viewport o dispositivo.
  • Container queries: Requieren definir primero un contenedor con container-type y luego usar @container para las condiciones.
/* Media query básica */
@media (max-width: 600px) {
  /* Estilos aquí */
}

/* Container query básica */
.container {
  container-type: inline-size;
}

@container (max-width: 400px) {
  /* Estilos aquí */
}

Esta diferencia estructural refleja sus distintos enfoques: las media queries son globales, mientras que las container queries están vinculadas a elementos específicos.

Configuración de elementos contenedores con container-type

Para utilizar las container queries, primero necesitamos definir qué elementos actuarán como contenedores. Esto se logra mediante la propiedad container-type, que establece un contexto de contención para los elementos descendientes.

La propiedad container-type es el punto de partida para trabajar con container queries, ya que define el elemento que servirá como referencia para las consultas de sus elementos hijos.

Valores de container-type

La propiedad container-type puede recibir diferentes valores según el tipo de contención que necesitemos:

.container {
  /* Opciones básicas de container-type */
  container-type: size;        /* Contención en ambas dimensiones */
  container-type: inline-size; /* Contención solo en dimensión inline */
  container-type: normal;      /* Sin contención (valor por defecto) */
}

Veamos en detalle cada uno de estos valores:

  • inline-size: Establece un contenedor que permite consultas basadas en la dimensión inline (generalmente el ancho en idiomas de izquierda a derecha). Es la opción más común y eficiente.

  • size: Crea un contenedor que permite consultas basadas en ambas dimensiones (ancho y alto). Tiene mayor impacto en el rendimiento que inline-size.

  • normal: Es el valor por defecto y no establece ningún contexto de contención.

Ejemplo básico de configuración

Veamos un ejemplo sencillo de cómo configurar un elemento como contenedor:

.card-container {
  container-type: inline-size;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

Con esta configuración, el elemento .card-container se convierte en un contenedor de referencia para las container queries que afectarán a sus elementos hijos.

Impacto en el rendimiento

Es importante entender que establecer un elemento como contenedor tiene implicaciones de rendimiento:

  • inline-size es más eficiente que size porque solo monitoriza cambios en una dimensión.
  • Cada contenedor requiere recursos adicionales del navegador para monitorizar sus cambios de tamaño.

Por esta razón, es recomendable usar container-type: inline-size a menos que realmente necesites consultas basadas en la altura.

Nombrar contenedores con container-name

Además de container-type, podemos utilizar la propiedad container-name para asignar un nombre específico a nuestros contenedores:

.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

/* Consulta específica para el contenedor nombrado */
@container sidebar (max-width: 300px) {
  .sidebar-widget {
    font-size: 0.8rem;
  }
}

Esto es especialmente útil cuando tenemos contenedores anidados y queremos asegurarnos de que nuestras consultas se apliquen al contenedor correcto.

Atajo con la propiedad container

Para simplificar, CSS ofrece la propiedad abreviada container que combina container-type y container-name:

/* Formato: container: <name> / <type>; */

.product-section {
  /* Equivalente a:
     container-name: products;
     container-type: inline-size; */
  container: products / inline-size;
}

/* Si solo queremos establecer el tipo sin nombre */
.simple-container {
  container: / inline-size;
}

Esta sintaxis abreviada es más concisa y se recomienda para la mayoría de los casos.

Contenedores anidados

Una característica poderosa de las container queries es la posibilidad de anidar contenedores, creando componentes que se adaptan en múltiples niveles:

.layout {
  container-type: inline-size;
}

.widget {
  container-type: inline-size;
}

/* Estilos para el widget basados en su propio contenedor */
@container (max-width: 200px) {
  .widget-title {
    font-size: 14px;
  }
}

En este ejemplo, .widget es tanto un elemento dentro del contenedor .layout como un contenedor en sí mismo para sus propios elementos hijos.

Ejemplo práctico: Tarjeta de producto adaptable

Veamos un ejemplo más completo de cómo configurar un contenedor para una tarjeta de producto:

/* Configuración del contenedor */
.product-card-wrapper {
  container-type: inline-size;
  container-name: card;
  
  /* Otras propiedades de estilo */
  padding: 1rem;
  border: 1px solid #eaeaea;
}

/* Estilos base de la tarjeta */
.product-card {
  display: grid;
  gap: 1rem;
}

/* Estilos que se aplicarán cuando el contenedor sea suficientemente ancho */
@container card (min-width: 350px) {
  .product-card {
    grid-template-columns: 120px 1fr;
    align-items: center;
  }
  
  .product-title {
    font-size: 1.2rem;
  }
}

/* Estilos para contenedores estrechos */
@container card (max-width: 349px) {
  .product-card {
    grid-template-columns: 1fr;
    text-align: center;
  }
  
  .product-image {
    margin: 0 auto;
    max-width: 150px;
  }
}

En este ejemplo:

  1. Definimos .product-card-wrapper como un contenedor con container-type: inline-size
  2. Le asignamos un nombre con container-name: card
  3. Creamos diferentes estilos para la tarjeta según el ancho del contenedor

Consideraciones importantes

Al configurar elementos contenedores, ten en cuenta estas recomendaciones:

  • Especificidad: Los elementos contenedores deben tener un tamaño definido o ser flexibles según su contexto.
  • Contención: Un elemento con container-type establecido crea un nuevo contexto de contención, similar a un nuevo contexto de formato.
  • Herencia: La propiedad container-type no se hereda, cada contenedor debe definirse explícitamente.
/* Ejemplo de configuración con consideraciones de tamaño */
.flexible-container {
  container-type: inline-size;
  width: 100%;      /* Ancho flexible */
  max-width: 600px; /* Límite máximo */
  margin: 0 auto;   /* Centrado */
}

Compatibilidad con navegadores

Aunque el soporte para container queries está creciendo rápidamente, es importante considerar la compatibilidad con navegadores:

/* Enfoque progresivo */
.card {
  /* Estilos base para todos los navegadores */
  display: grid;
  gap: 1rem;
}

/* Solo se aplicará en navegadores que soporten container queries */
@supports (container-type: inline-size) {
  .card-container {
    container-type: inline-size;
  }
  
  @container (min-width: 300px) {
    .card {
      grid-template-columns: 100px 1fr;
    }
  }
}

Utilizando @supports, podemos proporcionar una experiencia progresiva que funcione en todos los navegadores mientras aprovechamos las container queries donde estén disponibles.

Consultas basadas en el tamaño del contenedor

Una vez que hemos configurado nuestros elementos como contenedores utilizando container-type, podemos crear consultas específicas que respondan a sus dimensiones. Estas consultas nos permiten aplicar estilos diferentes según el tamaño del contenedor, no de la ventana del navegador.

La sintaxis básica de una container query utiliza la regla @container seguida de una condición de tamaño:

@container (condición) {
  /* Estilos que se aplicarán cuando se cumpla la condición */
}

Consultas de ancho y alto

Las consultas más comunes se basan en el ancho del contenedor, especialmente cuando usamos container-type: inline-size:

/* Estilos cuando el contenedor tiene al menos 400px de ancho */
@container (min-width: 400px) {
  .element {
    display: grid;
    grid-template-columns: 1fr 2fr;
  }
}

/* Estilos cuando el contenedor tiene como máximo 399px de ancho */
@container (max-width: 399px) {
  .element {
    display: flex;
    flex-direction: column;
  }
}

Si hemos configurado un contenedor con container-type: size, también podemos consultar por la altura:

/* Se aplica cuando el contenedor tiene al menos 300px de alto */
@container (min-height: 300px) {
  .tall-content {
    display: block;
  }
}

/* Combinación de ancho y alto */
@container (min-width: 500px) and (min-height: 400px) {
  .large-element {
    padding: 2rem;
  }
}

Consultas con nombres de contenedor

Cuando trabajamos con múltiples contenedores anidados, es recomendable usar nombres para dirigir nuestras consultas al contenedor específico:

.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

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

/* Consulta específica para el contenedor "sidebar" */
@container sidebar (max-width: 250px) {
  .sidebar-widget {
    font-size: 0.85rem;
  }
}

/* Consulta específica para el contenedor "content" */
@container content (min-width: 600px) {
  .article {
    column-count: 2;
  }
}

Esta técnica nos permite tener un control preciso sobre qué estilos se aplican a cada componente según su contexto.

Operadores lógicos en consultas

Podemos crear condiciones más complejas utilizando operadores lógicos:

/* AND: ambas condiciones deben cumplirse */
@container (min-width: 300px) and (max-width: 600px) {
  .medium-card {
    background-color: #f5f5f5;
  }
}

/* OR: al menos una condición debe cumplirse */
@container (max-width: 300px) or (min-width: 800px) {
  .special-case {
    border: 2px solid red;
  }
}

/* NOT: se aplica cuando la condición no se cumple */
@container not (min-width: 400px) {
  .small-only {
    display: block;
  }
}

Consultas con unidades relativas

Las container queries también funcionan con unidades relativas, lo que permite crear diseños más flexibles:

/* Se aplica cuando el contenedor tiene al menos 30em de ancho */
@container (min-width: 30em) {
  .responsive-text {
    font-size: 1.2rem;
  }
}

/* Usando porcentajes */
@container (min-width: 50%) {
  .half-width-trigger {
    margin: 2rem;
  }
}

Ejemplo práctico: Componente de tarjeta adaptable

Veamos un ejemplo completo de un componente de tarjeta que se adapta según el tamaño de su contenedor:

/* Configuración del contenedor */
.card-container {
  container-type: inline-size;
}

/* Estilos base de la tarjeta */
.card {
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
}

.card-content {
  padding: 1rem;
}

/* Diseño para contenedores pequeños (móvil) */
@container (max-width: 300px) {
  .card-image {
    aspect-ratio: 16/9;
    width: 100%;
  }
  
  .card-title {
    font-size: 1rem;
    margin-bottom: 0.5rem;
  }
  
  .card-description {
    display: none; /* Ocultar descripción en espacios muy pequeños */
  }
}

/* Diseño para contenedores medianos */
@container (min-width: 301px) and (max-width: 500px) {
  .card {
    display: grid;
    grid-template-columns: 120px 1fr;
  }
  
  .card-image {
    height: 100%;
    object-fit: cover;
  }
  
  .card-description {
    font-size: 0.9rem;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* Diseño para contenedores grandes */
@container (min-width: 501px) {
  .card {
    display: grid;
    grid-template-columns: 200px 1fr;
  }
  
  .card-content {
    padding: 1.5rem;
  }
  
  .card-title {
    font-size: 1.5rem;
    margin-bottom: 1rem;
  }
  
  .card-description {
    line-height: 1.6;
  }
}

Este componente se adaptará automáticamente según el espacio disponible en su contenedor, mostrando diferentes diseños y niveles de detalle.

Consultas de aspecto

Además del ancho y alto, podemos consultar por la relación de aspecto del contenedor:

/* Se aplica cuando el contenedor es más ancho que alto */
@container (aspect-ratio > 1/1) {
  .landscape-optimized {
    flex-direction: row;
  }
}

/* Se aplica cuando el contenedor es más alto que ancho */
@container (aspect-ratio < 1/1) {
  .portrait-optimized {
    flex-direction: column;
  }
}

Consultas de estilo

Las container queries también permiten consultar por propiedades de estilo del contenedor, no solo por sus dimensiones:

/* Se aplica cuando el contenedor tiene fondo oscuro */
@container style(background-color: #333) {
  .adaptive-text {
    color: white;
  }
}

/* Se aplica cuando el contenedor usa flex */
@container style(display: flex) {
  .flex-child {
    flex: 1;
  }
}

Esta característica es especialmente útil para crear componentes que se adaptan no solo al tamaño sino también al contexto visual.

Unidades de tamaño relativas al contenedor

CSS también proporciona unidades específicas para trabajar con container queries:

.card-title {
  /* 5% del ancho del contenedor más cercano con container-type */
  font-size: 5cqw;
}

.card-padding {
  /* 2% del alto del contenedor más cercano con container-type: size */
  padding: 2cqh;
}

.responsive-element {
  /* 3% de la dimensión más pequeña (ancho o alto) del contenedor */
  margin: 3cqi;
}

.adaptive-block {
  /* 4% de la dimensión más grande (ancho o alto) del contenedor */
  border-radius: 4cqb;
}

Estas unidades (cqw, cqh, cqi, cqb) son similares a las unidades de viewport (vw, vh, etc.) pero se basan en el contenedor en lugar de la ventana del navegador.

Estrategias para diseños complejos

Para diseños más complejos, podemos combinar múltiples niveles de container queries:

/* Contenedor principal */
.layout {
  container-type: inline-size;
  container-name: layout;
}

/* Contenedor secundario */
.widget {
  container-type: inline-size;
  container-name: widget;
}

/* Consulta para el layout principal */
@container layout (min-width: 800px) {
  .sidebar {
    display: block;
  }
}

/* Consulta para widgets dentro de la sidebar */
@container widget (max-width: 200px) {
  .widget-title {
    font-size: 0.9rem;
  }
}

Este enfoque nos permite crear interfaces que se adaptan en múltiples niveles, proporcionando una experiencia de usuario óptima en cualquier contexto.

Fallbacks y soporte progresivo

Para garantizar la compatibilidad con navegadores más antiguos, es recomendable proporcionar estilos base que funcionen sin container queries:

/* Estilos base para todos los navegadores */
.component {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

/* Mejoras para navegadores que soportan container queries */
@supports (container-type: inline-size) {
  .component-container {
    container-type: inline-size;
  }
  
  @container (min-width: 400px) {
    .component {
      flex-direction: row;
    }
  }
}

Este enfoque de mejora progresiva asegura que nuestro diseño sea funcional en todos los navegadores mientras aprovechamos las container queries donde estén disponibles.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

Plan mensual

19.00 € /mes

Precio normal mensual: 19 €
47 % DE DESCUENTO

Plan anual

10.00 € /mes

Ahorras 108 € al año
Precio normal anual: 120 €
Aprende CSS online

Ejercicios de esta lección Container queries

Evalúa tus conocimientos de esta lección Container queries con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Todas las lecciones de CSS

Accede a todas las lecciones de CSS y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Css

CSS

Introducción Y Entorno

Entorno Para Desarrollar Css

CSS

Introducción Y Entorno

Sintaxis

CSS

Sintaxis De Selectores Y Propiedades

Selectores Básicos

CSS

Sintaxis De Selectores Y Propiedades

Herencia Y Cascada

CSS

Sintaxis De Selectores Y Propiedades

Pseudo-clases Y Pseudo-elementos

CSS

Sintaxis De Selectores Y Propiedades

Colores En Css

CSS

Sintaxis De Selectores Y Propiedades

Unidades De Medida

CSS

Sintaxis De Selectores Y Propiedades

Especificidad

CSS

Sintaxis De Selectores Y Propiedades

Estilos De Fuente

CSS

Estilización De Texto Y Fondo

Propiedades De Texto

CSS

Estilización De Texto Y Fondo

Sombras En Texto Y Cajas

CSS

Estilización De Texto Y Fondo

Propiedades De Fondo

CSS

Estilización De Texto Y Fondo

Fuentes Web

CSS

Estilización De Texto Y Fondo

Efectos De Texto: Gradientes, Recortes

CSS

Estilización De Texto Y Fondo

Tipografía Avanzada

CSS

Estilización De Texto Y Fondo

Modelo De Caja

CSS

Modelo Caja

Propiedades De Posicionamiento

CSS

Modelo Caja

Propiedad 'Display'

CSS

Modelo Caja

Elementos 'Float' Y 'Clear'

CSS

Modelo Caja

Rellenos Y Márgenes

CSS

Modelo Caja

Bordes Y Contornos

CSS

Modelo Caja

Absolute, Fixed, Sticky Y Z-index

CSS

Posicionamiento

Flexbox Para Crear Layouts Y Estructuras

CSS

Flexbox

Css Grid Para Crear Layouts Y Estructuras

CSS

Flexbox

Propiedades Del Contenedor Flex

CSS

Flexbox

Propiedades De Los Items Flex

CSS

Flexbox

Columnas Y Filas En Grid

CSS

Css Grid

Espaciado Y Alineación

CSS

Css Grid

Tipografía Responsive

CSS

Diseño Responsive

Fundamentos Del Diseño Responsive

CSS

Diseño Responsive

Imágenes Responsive

CSS

Diseño Responsive

Funciones Matemáticas

CSS

Variables Y Funciones Css

Transformaciones 2d

CSS

Transformación, Transición, Animación

Transformaciones 3d

CSS

Transformación, Transición, Animación

Animaciones

CSS

Transformación, Transición, Animación

Transiciones

CSS

Transformación, Transición, Animación

Css Para Formularios

CSS

Css Avanzado

Accesibilidad Web Con Css

CSS

Css Avanzado

Container Queries

CSS

Css Avanzado

Selectores Avanzados

CSS

Css Avanzado

Animaciones Y Transiciones

CSS

Técnicas Modernas Y Metodologías

Variables En Css

CSS

Técnicas Modernas Y Metodologías

Diseño Responsive Con Media Queries

CSS

Técnicas Modernas Y Metodologías

Metodologías De Escritura En Css

CSS

Técnicas Modernas Y Metodologías

Accede GRATIS a CSS y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la diferencia fundamental entre media queries y container queries.
  • Aprender a configurar elementos contenedores con la propiedad container-type.
  • Saber cómo escribir consultas basadas en el tamaño y estilo del contenedor usando @container.
  • Conocer las ventajas de container queries para crear componentes reutilizables y adaptables en contextos variados.
  • Aplicar estrategias para compatibilidad y mejora progresiva en navegadores.