El problema del breakpoint
Por qué el punto de ruptura basado en el viewport es una abstracción que envejece mal, qué es el diseño intrínseco y cuáles son sus cuatro ingredientes.
El breakpoint nació como una respuesta razonable a un mundo con tres tamaños de pantalla y sobrevivió a ese mundo. Hoy un mismo componente puede aparecer a 320px dentro de una barra lateral en un monitor de 4K y a 900px en un móvil plegado en horizontal, y ninguna consulta sobre el ancho de la ventana distingue esos dos casos. El diseño intrínseco no es “responsive sin media queries” por deporte: es mover la decisión al sitio donde está la información, que es el espacio realmente disponible y el tamaño real del contenido.
- Explicar por qué el ancho de ventana es un mal proxy del espacio disponible de un componente.
- Cuantificar la explosión combinatoria de mantener varios juegos de breakpoints.
- Enumerar los cuatro ingredientes del layout intrínseco y qué aporta cada uno.
- Reescribir una regla basada en breakpoints como una restricción sobre el contenido.
El viewport no es el espacio disponible
Una media query pregunta por el ancho de la ventana. Lo que necesitas saber es cuánto espacio le queda a este componente después de que la barra lateral, los márgenes, el carril de lectura y los tres contenedores que hay por encima se hayan servido. Esas dos cantidades coinciden solo en un caso: cuando el componente ocupa el ancho completo del documento.
En cuanto un componente se reutiliza en dos contextos, la relación se rompe. La tarjeta que a 1400px de ventana tiene 1100px de ancho en la portada tiene 280px en el panel lateral del detalle. Con breakpoints solo tienes dos salidas, y las dos son malas: escribir variantes (tarjeta--compacta, tarjeta--ancha) que el consumidor debe recordar aplicar, o escribir reglas de contexto (.lateral .tarjeta) que acoplan el componente a todos los sitios donde vive.
El síntoma es reconocible: un componente que necesita saber dónde está para funcionar. Eso es una fuga de abstracción, y en CSS se paga en forma de reglas que nadie se atreve a borrar.
La explosión combinatoria
El coste de los breakpoints crece peor de lo que parece. Con cuatro puntos de ruptura y seis componentes que reaccionan a ellos ya tienes veinticuatro estados que alguien debería revisar. Añade dos modos de densidad y un cambio de idioma con textos un 30% más largos y el número de combinaciones deja de ser auditable por una persona.
Y hay un detalle que agrava el problema: los breakpoints son estado global. Un valor —el ancho de la ventana— gobierna decisiones de todos los componentes a la vez. Cuando alguien mueve 768px a 800px porque un componente se rompía, cambia el comportamiento de los otros veintitrés. Es exactamente la clase de acoplamiento que en el código de aplicación llevas años evitando.
Los 768px y 1024px que arrastra medio internet son el iPad de 2010. Los 320px, el iPhone original. Si tus breakpoints coinciden con modelos concretos de hardware, están describiendo un catálogo, no tu contenido. El breakpoint que sí envejece bien es el que sale de mirar dónde tu diseño empieza a verse mal, normalmente donde una línea de texto baja de unos 45 caracteres o donde una tarjeta baja del ancho al que su imagen deja de leerse.
Los cuatro ingredientes del diseño intrínseco
El término lo acuñó Jen Simmons en 2018 para nombrar lo que Grid y Flexbox permitían y el diseño de rejilla fluida de la década anterior no. Son cuatro capacidades, y las cuatro consisten en describir intenciones en vez de resultados.
Tamaños con mínimo y máximo. min(), max() y clamp() convierten cualquier dimensión en un rango con topes en vez de un número.
.carril { inline-size: min(70ch, 100% - 2rem); margin-inline: auto; }
.panel { inline-size: clamp(16rem, 30%, 24rem); }
Pistas flexibles. fr, minmax() y las funciones intrínsecas hacen que el reparto lo calcule el motor a partir de restricciones y no a partir de porcentajes que tú has dividido a mano.
El envolvimiento como mecanismo de primera clase. flex-wrap y repeat(auto-fit, ...) cambian el número de columnas sin que ninguna regla mencione un ancho de ventana. El punto de cambio se deduce de los tamaños que has declarado.
Contenido que participa en el cálculo. min-content, max-content y fit-content() meten el tamaño real del texto en la ecuación, que es la información que ninguna media query tiene.
Traducir una regla de breakpoint a una restricción
El ejercicio más útil es coger una regla existente y preguntarse qué intentaba decir.
/* Antes: describe el resultado en tres tamanos de ventana */
.galeria { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (width >= 40rem) { .galeria { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 64rem) { .galeria { grid-template-columns: repeat(3, 1fr); } }
@media (width >= 90rem) { .galeria { grid-template-columns: repeat(4, 1fr); } }
/* Despues: describe la intencion, una sola vez */
.galeria {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
gap: 1rem;
}
La versión de abajo no es más corta por casualidad: es más corta porque las cuatro reglas de arriba eran cuatro instancias de la misma frase, “que las tarjetas no bajen de 18rem”. Al declarar la frase directamente desaparecen las instancias, y con ellas la posibilidad de que una de las cuatro se quede desactualizada.
Hay una diferencia real de comportamiento y conviene conocerla: la versión con breakpoints garantiza exactamente 2, 3 o 4 columnas; la intrínseca garantiza un ancho mínimo pero no un número. Si el diseño exige “siempre tres”, el breakpoint no sobra. Si el diseño exige “tarjetas legibles”, sobra entero.
Lo que hace que un layout envejezca mal no es tener media queries: es dónde está guardado el conocimiento. Una regla como @media (width >= 64rem) { grid-template-columns: repeat(3, 1fr) } guarda el resultado de un cálculo que hiciste una tarde mirando una maqueta concreta, en un idioma concreto, con un contenido concreto. El razonamiento que lo produjo —“tres columnas de al menos 18rem con 1rem de hueco necesitan 58rem, más los márgenes, unos 64”— no está escrito en ninguna parte, y por tanto no se puede revalidar cuando cambia alguna de las premisas. Un minmax(18rem, 1fr) guarda la premisa y deja el cálculo al motor, que lo rehace en cada resize, en cada zoom, en cada cambio de fuente y en cada contenedor. La consecuencia práctica es contraintuitiva: el layout intrínseco no es más flexible porque sea más listo, sino porque contiene menos decisiones ya tomadas. Cada constante que eliminas es una hipótesis sobre el futuro que dejas de tener que defender. Esto es exactamente por qué la solución no es prohibir las media queries, sino usarlas solo donde la decisión sea genuinamente sobre el dispositivo y no sobre el contenido.