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ícateDiferencias 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 queinline-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 quesize
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:
- Definimos
.product-card-wrapper
como un contenedor concontainer-type: inline-size
- Le asignamos un nombre con
container-name: card
- 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.
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.
Reto modelo caja CSS
Propiedades de posicionamiento
Modelo de caja
Sombras en texto y cajas
Reto implementación de fuentes web
Sintaxis básica
Estilos de fuente
Diseño responsive con media queries
Animaciones y transiciones
Proyecto CSS Landing page simple
Reto unidades de medida
Propiedades de texto
Metodologías BEM, SMACSS, OOCSS
Herencia y cascada
Sintaxis avanzada
Reto fondos background CSS
Reto sintaxis CSS
Flexbox en diseños modernos
Elementos 'float' y 'clear'
Pseudo-clases y pseudo-elementos
Reto grid de columnas en CSS
Selectores avanzados
Reto componente responsive
Reto formulario estilizado
Proyecto CSS crear una navbar
Proyecto CSS Dashboard Responsive
Reto Flexbox Hero
Propiedades de fondo
Introducción a CSS
Reto selectores básicos CSS
Reto Flexbox Card
Reto propiedades texto
Modelo de caja
Propiedad 'display'
Variables en CSS
Grid en diseños de cuadrícula
Selectores básicos
Reto tema claro/oscuro con variables
Reto especificidad y cascada
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
Introducción Y Entorno
Entorno Para Desarrollar Css
Introducción Y Entorno
Sintaxis
Sintaxis De Selectores Y Propiedades
Selectores Básicos
Sintaxis De Selectores Y Propiedades
Herencia Y Cascada
Sintaxis De Selectores Y Propiedades
Pseudo-clases Y Pseudo-elementos
Sintaxis De Selectores Y Propiedades
Colores En Css
Sintaxis De Selectores Y Propiedades
Unidades De Medida
Sintaxis De Selectores Y Propiedades
Especificidad
Sintaxis De Selectores Y Propiedades
Estilos De Fuente
Estilización De Texto Y Fondo
Propiedades De Texto
Estilización De Texto Y Fondo
Sombras En Texto Y Cajas
Estilización De Texto Y Fondo
Propiedades De Fondo
Estilización De Texto Y Fondo
Fuentes Web
Estilización De Texto Y Fondo
Efectos De Texto: Gradientes, Recortes
Estilización De Texto Y Fondo
Tipografía Avanzada
Estilización De Texto Y Fondo
Modelo De Caja
Modelo Caja
Propiedades De Posicionamiento
Modelo Caja
Propiedad 'Display'
Modelo Caja
Elementos 'Float' Y 'Clear'
Modelo Caja
Rellenos Y Márgenes
Modelo Caja
Bordes Y Contornos
Modelo Caja
Absolute, Fixed, Sticky Y Z-index
Posicionamiento
Flexbox Para Crear Layouts Y Estructuras
Flexbox
Css Grid Para Crear Layouts Y Estructuras
Flexbox
Propiedades Del Contenedor Flex
Flexbox
Propiedades De Los Items Flex
Flexbox
Columnas Y Filas En Grid
Css Grid
Espaciado Y Alineación
Css Grid
Tipografía Responsive
Diseño Responsive
Fundamentos Del Diseño Responsive
Diseño Responsive
Imágenes Responsive
Diseño Responsive
Funciones Matemáticas
Variables Y Funciones Css
Transformaciones 2d
Transformación, Transición, Animación
Transformaciones 3d
Transformación, Transición, Animación
Animaciones
Transformación, Transición, Animación
Transiciones
Transformación, Transición, Animación
Css Para Formularios
Css Avanzado
Accesibilidad Web Con Css
Css Avanzado
Container Queries
Css Avanzado
Selectores Avanzados
Css Avanzado
Animaciones Y Transiciones
Técnicas Modernas Y Metodologías
Variables En Css
Técnicas Modernas Y Metodologías
Diseño Responsive Con Media Queries
Técnicas Modernas Y Metodologías
Metodologías De Escritura En Css
Técnicas Modernas Y Metodologías
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.