Mira la lección en vídeo
Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.
Desbloquear Plan PlusDiferencias 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
Guarda tu progreso
Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.
Más de 25.000 desarrolladores ya confían en CertiDevs
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.
Aprendizajes de esta lección de CSS
- 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.
Completa este curso de CSS y certifícate
Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.
Asistente IA
Resuelve dudas al instante
Ejercicios
Practica con proyectos reales
Certificados
Valida tus conocimientos
Más de 25.000 desarrolladores ya se han certificado con CertiDevs