Tres horas. Media hora para entender qué resuelve Grid que Flexbox no y por qué la mayoría de las adaptaciones no necesitan media query, y dos horas y media construyendo un catálogo que se adapta solo y rompiendo tu sitio a cinco anchuras.
Hoy · Hoja de ruta
- 1. Aprende: Qué problema bidimensional resuelve Grid, qué significa
fr, cómo hacer que el número de columnas lo decida el espacio y dónde va de verdad un breakpoint. - 2. Haz: Convierte el catálogo en cuadrícula, monta el esqueleto de página con áreas y recorre tu sitio a cinco anchuras corrigiendo lo que se rompa.
- 3. Comprueba: No hay scroll horizontal entre 320 px y 1600 px, y cada media query que hayas escrito responde a un problema que sabes nombrar.
Antes de empezar · 5 minutos, sin apuntes
- ¿Cuál es la diferencia entre
marginygap? - ¿Qué hace
flex-wrap? - Decide si una botonera, una tarjeta horizontal y un catálogo necesitan Flexbox, Grid o ninguno.
Se explica
25 minutos · conceptos y demostración
La sesión tiene una sola idea de fondo: deja de decir cuántas columnas quieres y describe cuánto necesita cada una. Grid es la herramienta que lo permite, y el responsive es lo que sale de aplicarla bien.
Dos dimensiones a la vez
Flexbox coloca en una línea. Considera ahora este problema:
Producto Producto Producto
Producto Producto Producto
Producto Producto Producto
Aquí no hay una dirección: hay filas y columnas, y quieres que las columnas estén alineadas entre filas. Con Flexbox se puede aproximar, y las columnas nunca acaban de cuadrar porque cada fila reparte su espacio por su cuenta. Grid está diseñado exactamente para esto.
.catalogo {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 1.5rem;
}
Nova 14
Portátil ligero
Vision 27
Monitor IPS
Type Pro
Teclado mecánico
Dock One
Base USB-C
Wave
Ratón inalámbrico
Focus
Webcam 2K
Grid alinea cada tarjeta con las columnas de las demás filas; por eso es una herramienta bidimensional.
Tres declaraciones y tienes una cuadrícula de tres columnas con sus filas alineadas. Fíjate en que no has dicho cuántas filas hay: Grid las crea según los elementos que haya.
fr
Una fracción del espacio libre del contenedor. 1fr 1fr 1fr reparte lo disponible en tres partes iguales; 2fr 1fr da el doble a la primera columna.
Es distinta del porcentaje, y la diferencia importa: 33.33% no descuenta el gap, así que tres columnas al 33.33 % con separación desbordan. 1fr sí lo descuenta, porque reparte lo que queda después de los huecos. Por eso con Grid no tienes que hacer cuentas.
grid-template-columns: repeat(3, 1fr); /* lo mismo, sin repetirte */
grid-template-columns: 250px 1fr; /* una fija y otra elástica */
grid-template-columns: 1fr 2fr; /* una parte y dos partes */
El vocabulario, y por qué se cuentan líneas
- Líneas · las divisiones, numeradas desde 1
- Pistas · las columnas y filas que quedan entre líneas
- Celdas · el cruce de una columna con una fila
- Áreas · un grupo rectangular de celdas, que puedes nombrar
Conviene fijarse en que se numeran las líneas, no las columnas. Una cuadrícula de tres columnas tiene cuatro líneas verticales: la 1 al principio y la 4 al final. Es la fuente de casi todos los desajustes de la sesión.
Usa siempre el inspector de Grid
En DevTools, junto a un elemento con display: grid, aparece una etiqueta grid. Púlsala y el navegador dibuja encima de la página las líneas con su numeración, las pistas y los huecos.
No intentes imaginar mentalmente una cuadrícula compleja si el navegador puede dibujártela. Cuando un elemento no cae donde esperabas, el inspector te enseña en un segundo qué línea es la 3 de verdad.
La línea más rentable de la unidad
.catalogo {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
gap: 1.5rem;
}
Léela de dentro afuera:
minmax(16rem, 1fr) cada columna mide como poco 16rem,
y crece para repartirse lo que sobre
auto-fit caben las que quepan; el número
lo decide el espacio disponible
Es decir: deja de decir cuántas columnas quieres y describe cuánto necesita cada una. En un móvil cabrá una, en una tablet dos, en un monitor cuatro, y no has escrito una sola media query.
Áreas con nombre
Para el esqueleto de una página completa hay una forma que se lee sola:
.layout {
display: grid;
grid-template-columns: 15rem 1fr;
grid-template-areas:
"cabecera cabecera"
"lateral principal"
"pie pie";
gap: 1rem;
}
header { grid-area: cabecera; }
aside { grid-area: lateral; }
main { grid-area: principal; }
footer { grid-area: pie; }
El dibujo entre comillas es el layout. Se ve de un vistazo que la cabecera ocupa las dos columnas y que el lateral está a la izquierda del contenido. Para modificarlo en una pantalla estrecha basta con redibujarlo:
@media (width < 48rem) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"cabecera"
"principal"
"lateral"
"pie";
}
}
Fíjate en un detalle importante: en la pantalla estrecha el contenido va antes que el lateral, y el HTML no ha cambiado. Grid permite reordenar visualmente.
Reordenar visualmente tiene un límite
El orden del teclado sigue al HTML, no al CSS. Si mueves visualmente un bloque muy lejos de su sitio en el documento, quien navegue con Tab saltará de un lado a otro de la pantalla sin lógica aparente.
Reordenar el lateral y el contenido, que están contiguos, es inofensivo. Reordenar a lo grande no lo es. Si el orden visual y el del documento tienen que diferir mucho, lo que está mal es el orden del HTML.
Flexbox o Grid
No compiten. Una regla inicial que funciona:
- Una dimensión · Flexbox
- Filas y columnas a la vez · Grid
Una segunda pregunta afina la decisión: ¿quién debería decidir el tamaño, el contenedor o el contenido? Grid define la cuadrícula desde fuera y el contenido se acomoda; Flexbox parte de los elementos y reparte lo que sobra. Un menú cuyos enlaces miden cada uno lo suyo es Flexbox. Un catálogo cuyas tarjetas deben coincidir es Grid.
Lo más habitual en código real es que convivan:
GRID para distribuir las tarjetas
↓
FLEXBOX dentro de cada tarjeta
Primero fluido, después media queries
Quien entre a tu sitio puede hacerlo desde un móvil, una tablet, un portátil, un monitor grande, media pantalla en una ventana dividida, o un dispositivo que todavía no existe. No puedes enumerarlos.
- Primero, que el diseño se adapte solo
- Después, media queries solo donde el contenido ya no funcione
Llevas cuatro semanas construyendo herramientas que adaptan solas:
| Herramienta | Qué adapta sola |
|---|---|
max-width y min() |
La anchura de los contenedores |
flex-wrap |
El salto de línea cuando no caben |
auto-fit con minmax() |
El número de columnas del catálogo |
clamp() |
El tamaño de los titulares |
gap |
La separación, sin cuentas |
Si las usas bien, buena parte de tu sitio ya es responsive y no lo sabías. Las media queries son para lo que queda.
Mobile first
Escribir primero los estilos de la disposición más sencilla —una columna— y añadir después las variantes para pantallas anchas con min-width, en lugar de al revés.
/* Base: una columna. Vale para cualquier pantalla. */
.catalogo {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
}
@media (width >= 48rem) {
.catalogo { grid-template-columns: repeat(2, 1fr); }
}
@media (width >= 70rem) {
.catalogo { grid-template-columns: repeat(3, 1fr); }
}
Mobile first parte de una columna y añade capacidad solo cuando el contenido dispone de espacio suficiente.
La razón no es ideológica: el caso de una columna es el más simple, y partir de lo simple para añadir complejidad da menos código que partir de lo complejo para irlo deshaciendo. La sintaxis (width >= 48rem) es la moderna y se lee sola; encontrarás también la clásica, (min-width: 48rem), que significa lo mismo.
Los breakpoints no son teléfonos
No busques las medidas del iPhone 15 ni del Galaxy de turno. Esa lista cambia cada año y nunca está completa.
Un breakpoint va donde tu contenido deja de funcionar: donde el menú ya no cabe, donde una columna se queda demasiado estrecha para leerse, donde la tarjeta se rompe. Esa anchura se encuentra estirando la ventana hasta que se ve mal, y es distinta en cada proyecto porque cada proyecto tiene otro contenido.
Ese es el motivo de que el paso 1 pida anotar a qué anchura empieza a verse mal el catálogo. Ese número vale más que cualquier lista de dispositivos.
Se trabaja
150 minutos · práctica sobre tu propio proyecto
El paso 1 provoca el problema a propósito y no lo arregla; el paso 2 lo resuelve con una sola línea. Los cuatro restantes llevan esa idea al sitio entero.
Paso 1 · Tu catálogo en cuadrícula · 20 min
En productos.html, convierte el contenedor de las fichas en un Grid.
- Aplica
display: gridygapal contenedor de losarticle. - Prueba
repeat(2, 1fr), despuésrepeat(3, 1fr)y despuésrepeat(4, 1fr). Quédate con la que mejor te encaje en tu pantalla. - Abre el inspector de Grid y localiza las líneas, las pistas y los huecos.
- Ahora estrecha la ventana hasta 400 px y observa qué pasa con las tarjetas.
Todavía no lo arregles
Vas a ver columnas ridículamente estrechas, con una palabra por línea. Es lo esperado, y es el problema que resuelve el paso siguiente.
Anota qué has visto y a qué anchura ha empezado a verse mal. Ese número es tu primer breakpoint candidato, y lo has obtenido de la única forma legítima: mirando cuándo el contenido deja de funcionar.
Paso 2 · El catálogo que se adapta solo · 25 min
Aplica auto-fit con minmax() a tu página de productos. Comprueba de 320 px a 1600 px que en ningún momento hay columnas ilegibles ni tarjetas gigantes.
- Elige el mínimo de
minmax()a partir del número que anotaste en el paso 1, no de una cifra redonda. - Prueba también con
auto-filly explica en un comentario cuál has elegido y por qué. - Comprueba con el inspector cuántas columnas hay a 320, 768, 1024 y 1600 px.
Consultar · auto-fit frente a auto-fill
Se parecen y hacen cosas distintas cuando sobra sitio:
| Con pocos elementos y mucho espacio | |
|---|---|
auto-fit |
Las columnas vacías se colapsan, y las que hay se estiran para ocuparlo todo |
auto-fill |
Se mantienen las columnas vacías, y los elementos conservan su tamaño |
La forma de verlo es la experimentación: pon tres tarjetas en una pantalla ancha y cambia una palabra por la otra. Con auto-fit las tres se estiran; con auto-fill se quedan a la izquierda con su tamaño.
Paso 3 · El esqueleto de página con áreas · 30 min
Construye este layout con grid-template-areas:
┌───────────────────────────┐
│ HEADER │
├─────────┬─────────────────┤
│ ASIDE │ MAIN │
│ │ │
├─────────┴─────────────────┤
│ FOOTER │
└───────────────────────────┘
y su versión en una columna para pantallas estrechas, con el contenido antes que el lateral. Decide tú a qué anchura cambia, y justifícalo por el contenido.
Consultar · colocar un elemento en celdas concretas
A veces un elemento debe ocupar más de una celda:
.destacado {
grid-column: 1 / 3; /* de la línea 1 a la 3: dos columnas */
}
.destacado {
grid-column: span 2; /* dos columnas, empiece donde empiece */
}
span suele ser más robusto: no depende de dónde acabe cayendo el elemento, cosa que cambia al variar el número de columnas.
Estoy atascado · un elemento no cae donde quiero
Abre el inspector de Grid y mira la numeración real de las líneas. El error casi siempre es contar columnas en lugar de líneas: para ocupar las dos primeras columnas hace falta 1 / 3, no 1 / 2.
Y si usas áreas, comprueba que todas las filas del dibujo tienen el mismo número de nombres. Si una fila tiene dos y otra tres, la plantilla entera es inválida y se ignora en silencio.
Paso 4 · ¿Flexbox, Grid, los dos o ninguno? · 15 min
Para cada interfaz, decide y justifica en una frase:
- La navegación principal.
- Una galería de imágenes en cuadrícula.
- Una botonera de dos botones.
- Un formulario de etiquetas y campos, uno debajo de otro.
- El catálogo de productos.
- Un panel con seis indicadores, uno de ellos del doble de ancho.
- La barra de precio y botón dentro de una tarjeta.
- El pie con tres columnas de enlaces.
Ver respuesta
1 · Flexbox. Una línea de enlaces que miden lo que miden.
2 · Grid. Filas y columnas que deben alinearse.
3 · Flexbox. Una dimensión y dos elementos.
4 · Ninguno. El flujo normal ya apila bloques; basta con márgenes o un gap si lo envuelves. No todo necesita un sistema de layout.
5 · Grid para la cuadrícula, y Flexbox dentro de cada tarjeta. Los dos.
6 · Grid. Además el indicador ancho se resuelve con span 2, que en Flexbox sería incómodo.
7 · Flexbox con space-between. Una dimensión.
8 · Grid si las tres columnas deben tener el mismo ancho; Flexbox si cada una puede medir lo suyo. Aquí las dos respuestas son defendibles, y lo que se evalúa es la justificación.
Paso 5 · Rompe tu página · 45 min
Es el trabajo central de la sesión. Con DevTools en modo dispositivo, recorre tu sitio a estas anchuras:
320 px móvil pequeño
375 px móvil habitual
768 px tablet
1024 px portátil
1440 px escritorio
Busca a continuación, en las cuatro páginas:
| Problema | ¿Dónde aparece? | A qué anchura | Cómo lo has resuelto |
|---|---|---|---|
| Contenido que se sale | |||
| Scroll horizontal | |||
| Navegación que no cabe | |||
| Imágenes demasiado grandes | |||
| Columnas demasiado estrechas | |||
| Texto difícil de leer |
Después corrígelos, intentando primero sin media query. Si lo resuelves con flex-wrap, con minmax() o con clamp(), mejor que con un breakpoint: no hay que mantenerlo.
Estoy atascado · tengo scroll horizontal y no sé de dónde sale
Es de los fallos más frustrantes, porque el culpable puede estar en cualquier sitio. Sospechosos por orden de frecuencia:
- Una imagen sin
max-width: 100%. - Un
widthfijo en píxeles mayor que la pantalla. - Un elemento con
100%más unpadding, sinbox-sizing: border-box. - Una tabla, o un bloque de código, que no cabe y no tiene su propio
overflow-x: auto. - Un
marginnegativo.
Para localizarlo rápido, en la consola de DevTools puedes recorrer los elementos y ver cuál es más ancho que el documento. O, de forma más rudimentaria: ve dando outline: 1px solid red a secciones enteras hasta ver cuál se sale.
Paso 6 · Defiende cada breakpoint · 15 min
Recorre todas las media queries de tu hoja y rellena una fila por cada una:
| Anchura | Qué deja de funcionar exactamente a esa anchura | ¿Se podía resolver sin media query? |
|---|---|---|
Elimina las que no puedas defender. Una media query que está ahí «por si acaso», o copiada de una lista de dispositivos, es código que habrá que mantener sin saber qué protege.
Ampliación si has completado el trabajo
Primero termina y comprueba los seis pasos. El segundo reto es el que más enseña de los dos, y consiste en borrar código.
Reto 1 · Un panel de indicadores
Construye un panel de seis indicadores con estas condiciones, sin una sola media query:
┌─────────────────┬────────┐
│ FACTURACIÓN │ PEDIDOS│
│ (doble ancho) │ │
├────────┬────────┼────────┤
│ STOCK │ DEVOL. │ VISITAS│
├────────┴────────┴────────┤
│ INCIDENCIAS │
│ (todo el ancho) │
└──────────────────────────┘
- Usa
auto-fitconminmax()para las columnas, yspanpara los dos indicadores anchos. - Comprueba qué ocurre a 320 px, donde solo cabe una columna. Un
span 2en una cuadrícula de una sola columna puede romper el layout: averigua qué pasa exactamente y resuélvelo. - Consigue que los seis indicadores tengan la misma altura aunque su contenido sea de longitudes distintas. Di si eso lo resuelve Grid o Flexbox, y por qué.
- Anota en cuántas disposiciones distintas se reorganiza el panel entre 320 y 1600 px. No las has escrito: las decide el contenido.
Reto 2 · Quitar breakpoints
Esta hoja resuelve un catálogo y una cabecera con seis media queries. Todas funcionan, y la mayoría sobran.
.catalogo { display: grid; grid-template-columns: 1fr; gap: 16px; }
.tarjeta h3 { font-size: 18px; }
.cabecera { display: flex; justify-content: space-between; }
.contenedor { width: 100%; padding: 0 16px; }
@media (min-width: 480px) { .catalogo { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 768px) { .catalogo { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px){ .catalogo { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 768px) { .tarjeta h3 { font-size: 22px; } }
@media (min-width: 1280px){ .tarjeta h3 { font-size: 26px; } }
@media (min-width: 1280px){ .contenedor { width: 1240px; margin: 0 auto; padding: 0; } }
- Sustituye las tres primeras por una sola declaración sin media query.
- Sustituye las dos del titular por una sola declaración sin media query.
- Sustituye la del contenedor por una que no fije una anchura en píxeles.
- ¿Cuántas media queries quedan al terminar? Si queda alguna, defiéndela: di qué problema de contenido resuelve que no se pueda resolver de otro modo.
- Compara el número de líneas de las dos versiones y el número de valores que habría que revisar si mañana cambia el diseño.
Cierre
5 minutos · comprobación y recuerdo
Lista de verificación de la sesión
- Tu catálogo se adapta sin media queries.
- No hay scroll horizontal a 320 px en ninguna página.
- Cada media query que has escrito responde a un problema concreto que puedes nombrar.
- Ninguno de tus breakpoints procede de un modelo de teléfono.
- Sabes justificar, para cada bloque, si es Flexbox o Grid.
- El esqueleto de página usa áreas con nombre y se reordena en pantalla estrecha.
Antes de cerrar · 3 minutos, sin mirar
- ¿Por qué
1frno es lo mismo que33.33%? - Una cuadrícula de cuatro columnas, ¿cuántas líneas verticales tiene?
- ¿Qué hace
repeat(auto-fit, minmax(16rem, 1fr)), en una frase? - ¿Qué riesgo tiene reordenar visualmente con Grid?
- ¿Qué significa mobile first y por qué se hace así?
- ¿Dónde debe ir un breakpoint?
Ver respuestas
1 · Porque fr reparte el espacio que queda después de descontar los gap, y el porcentaje no los descuenta.
2 · Cinco: una a cada lado de cada columna, contando los dos extremos.
3 · Crea tantas columnas como quepan, de al menos 16rem cada una, repartiéndose el espacio sobrante.
4 · Que el orden del teclado sigue al HTML, así que un reordenado grande hace que el foco salte por la pantalla sin lógica.
5 · Escribir primero la disposición más simple y añadir después las de pantallas anchas. Porque partir de lo simple y añadir sale más corto que partir de lo complejo y deshacer.
6 · Donde el contenido deja de funcionar, no donde está un modelo de dispositivo.
Microprueba semanal 4 · 5–10 minutos
Individual, sin IA y sin apuntes.
- Decide entre Flexbox, Grid o flujo normal para tres interfaces que no has visto.
- Escribe un Grid adaptable sin media query.
- Una página desborda a 360 px: enumera tres comprobaciones antes de añadir un breakpoint.