Ir al contenido
wannacode

Grid: filas y columnas

En resumen: CSS Grid coloca los elementos a la vez en filas y columnas: columnas con fr y gap, un catálogo con repeat(auto-fill, minmax()) y una disposición de página con grid-template-areas.

Problema

El último producto es enorme

El catálogo usa flex-wrap de la lección anterior. Cuatro productos: tres caben en la primera línea, y el cuarto está solo en la segunda línea y es tan ancho como toda la línea.

HTML, CSS, JS

Esto no es un error de flexbox. Cada línea de un contenedor flex reparte su propio espacio libre y no sabe nada de la línea de arriba. La segunda línea tiene un producto, así que toma todo: 768px. Necesitamos algo que dibuje las columnas una sola vez para todo el catálogo.

La idea

Filas y columnas

Grid es una disposición en dos dimensiones: el contenedor dibuja columnas y filas, y los elementos van a las celdas uno a uno, fila por fila.

.catalog {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: 24px;
}
  • display: grid convierte el elemento en un contenedor grid, y sus hijos son elementos grid.
  • grid-template-columns dice cuántas columnas hay y cuánto mide cada una: 200px 1fr es una columna de 200px y otra que toma el resto.
  • fr es una parte del espacio libre, una vez quitadas las columnas de tamaño fijo y los gap. 1fr 2fr 1fr es 1 : 2 : 1.
  • repeat(3, 1fr) es lo mismo que 1fr 1fr 1fr.
  • gap es el espacio entre las columnas y entre las filas.

La diferencia con flexbox: con flex los elementos deciden su ancho, y cada línea va por separado. Con grid el contenedor decide las columnas, y los elementos solo las llenan. Por eso el último producto se queda en su columna.

Pruébalo

Tres columnas

Haz del catálogo un grid con tres columnas iguales y un gap de 24px. El catálogo llega hasta 720px, así que cada tarjeta, también la última, tiene que medir (720 − 2 × 24) : 3 = 224px.

HTML, CSS, JS

La idea

Tantas como quepan

Tres columnas están bien en una computadora. En un teléfono miden 100px cada una y el producto no se puede leer. No queremos dar el número, sino una regla: «columnas de al menos 200px, tantas como quepan».

grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  • minmax(200px, 1fr): la columna mide al menos 200px y como máximo una parte.
  • auto-fill en lugar de un número: el navegador pone tantas columnas del ancho mínimo como quepan, contando los gap.
  • Después el resto se reparte por igual (1fr), y las columnas crecen hasta el final de la fila.

Míralo

Mira cómo se cuentan

La misma regla en un catálogo de 960, 680 y 328px.

.catalog {
display: grid;
grid-template-columns:
repeat(auto-fill, minmax(200px, 1fr));
gap: 16px;
}
Paso a paso, en palabras
  1. El catálogo es un grid. Las columnas no se dan con un número, sino con una regla: tantas como quepan, cada una de al menos 200px.
  2. Un catálogo de 960px. El navegador coloca columnas de 200px con un gap de 16px mientras quepan: 4 × 200 + 3 × 16 = 848px. Una quinta llegaría a 1064px: no cabe.
  3. Sobran 960 − 848 = 112px. 1fr los reparte por igual: cada columna mide (960 − 3 × 16) : 4 = 228px.
  4. Con 680px caben tres columnas (3 × 200 + 2 × 16 = 632). Una cuarta necesitaría 848. Cada una mide (680 − 32) : 3 = 216px.
  5. Con 328px, un teléfono, cabe una: dos necesitarían 416px. Ocupa todo el ancho: 328px.
  6. Una regla, tres disposiciones. El número de columnas sigue el ancho del catálogo, sin media queries. Los productos llenan las columnas fila por fila.

El mismo catálogo como página, primero en un teléfono (360px) y luego en una computadora (1000px). El código es el mismo.

HTML, CSS, JS
HTML, CSS, JS

Las columnas dependen del ancho del catálogo, no del de la pantalla. Un catálogo en una columna estrecha de la página tiene menos columnas, incluso en una pantalla grande.

Pruébalo

Una regla para los dos sitios

La página tiene un catálogo y una columna estrecha «También compraron» (220px). Los dos son .catalog con flex-wrap, y el último producto del catálogo es demasiado ancho. Cambia la regla de .catalog: grid, columnas de al menos 200px, tantas como quepan, estiradas hasta el final. La comprobación espera 3 columnas en el catálogo, cada una de 208px, y 1 columna de 220px a la derecha.

HTML, CSS, JS

La idea

Áreas de la página

Grid también coloca la propia página: la cabecera, los filtros a la izquierda, el catálogo, el pie. Las áreas se pueden dibujar con nombres:

.page {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-areas:
"header header"
"filters main"
"footer footer";
gap: 16px;
}
header { grid-area: header; }
.filters { grid-area: filters; }
  • Cada línea entre comillas es una fila del grid, y cada palabra es una celda. Una palabra en dos celdas contiguas forma un área que ocupa las dos: la cabecera abarca dos columnas.
  • grid-area: header coloca el elemento en el área con ese nombre.
  • Cada fila tiene que tener tantas celdas como columnas hay, y un área tiene que ser un rectángulo.

Sin nombres, un elemento se coloca por los números de las líneas entre las columnas: grid-column: 1 / 3 va de la primera a la tercera línea (dos columnas), y grid-column: 1 / -1 llega hasta la última línea. grid-column: span 2 ocupa dos columnas allí donde el navegador lo ponga.

Pruébalo

La página

Coloca la página (900px) con grid-template-areas: arriba la cabecera sobre todo el ancho, debajo los filtros a la izquierda (220px) y el catálogo a la derecha, y abajo el pie sobre todo el ancho. El gap es de 16px.

HTML, CSS, JS

Pruébalo

Encuentra el error

La página se ha desmontado: la cabecera, los filtros, el catálogo y el pie están unos encima de otros. La consola no muestra ningún error. ¿Qué línea es la causa?

Elige la línea con el error.

Más precisamente, para curiosos

Filas implícitas. grid-template-columns y grid-template-rows describen el grid explícito. Si hay más elementos, el navegador añade filas por su cuenta. Son implícitas y valen auto, tan altas como el contenido. Su altura se define con grid-auto-rows.

auto-fill y auto-fit. La diferencia se ve cuando hay menos elementos que columnas. En un catálogo de 960px con dos productos, auto-fill mantiene las cuatro columnas, y los productos miden 228px cada uno. auto-fit elimina las columnas vacías, y los dos productos pasan a medir 472px cada uno.

fr y el contenido. 1fr es minmax(auto, 1fr): la columna no se hace más estrecha que la palabra más larga que contiene. Si una palabra larga estira la columna, minmax(0, 1fr) la frena.

Grid o flex. Flexbox es para un eje: una cabecera, una fila de botones, una línea del carrito. Grid es para dos: un catálogo, una página, un panel. A menudo van juntos: la página es un grid, y la cabecera de dentro es flex.

Más. grid-auto-flow: dense rellena las celdas vacías con elementos posteriores, pero altera el orden en la pantalla respecto al árbol. subgrid deja que un grid anidado use las columnas de su padre.

Ejercicio

El producto de la semana

Haz del catálogo (900px) un grid: columnas de al menos 200px, tantas como quepan, gap de 16px. El producto de la semana va primero y ocupa dos columnas. Todas las filas miden 160px de alto, también las que añada el navegador por su cuenta. La comprobación espera 4 columnas de 213px, el producto de la semana de 442px de ancho y el último producto de 160px de alto.

HTML, CSS, JS

Test

Ponte a prueba

1. Un catálogo de 700px tiene grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) y gap: 20px. ¿Cuántas columnas tiene?
2. ¿Cuándo es grid mejor opción que flexbox?
3. ¿Qué hace grid-column: span 2?
4. El grid tiene grid-template-rows: 160px, y los productos están en tres filas. ¿Cuánto miden de alto la segunda y la tercera fila?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·