Grid
Lección 12 de 37 · 4 min
Grid acomoda los hijos de una caja en columnas y filas a la vez. Vos definís las columnas y el navegador reparte el espacio.
Columnas y gap
Con display: grid la caja se vuelve una grilla, y cada hijo directo ocupa una celda. Dos propiedades alcanzan para empezar:
- Columnas
grid-template-columnsLa lista de columnas, un tamaño por columna. Las filas se crean solas, a medida que hacen falta. - Espacio
gapEl espacio entre columnas y entre filas. Va solo entre celdas, nunca contra el borde de la grilla.
Elegí una plantilla y mové el gap en el menú del café: la regla naranja de arriba marca el ancho de cada columna, y el rayado entre platos es el gap.
.menu {display: grid;grid-template-columns: 1fr 1fr 1fr;gap: 12px;}
<ul class="grid grid-cols-3 gap-3"><li>Latte</li><li>Bowl</li><li>Crepes</li><li>Salmón</li><li>Parfait</li><li>Scon</li></ul>
La grilla mide 288px. Con 1fr 1fr 1fr y un gap de 12px quedan 264px para repartir, así que cada columna mide 88px. Los seis platos llenan la primera fila y siguen en la segunda, en orden.
La unidad fr
fr es una fracción del espacio libre: lo que sobra después de restar las columnas de tamaño fijo y los gaps. El navegador suma los fr y reparte en proporción. En la grilla de 288px con gap de 12px:
- Proporción
1fr 2frSobran 276px. Hay 3fr en total, así que la primera columna se lleva un tercio, 92px, y la segunda dos tercios, 184px. - Fijo y flexible
200px 1frLa primera mide 200px fijos y la segunda se queda con el resto, 288 − 200 − 12 = 76px.
repeat() evita escribir lo mismo varias veces: repeat(3, 1fr) equivale a 1fr 1fr 1fr. minmax() le pone un mínimo y un máximo a una columna. Juntos arman una grilla que se adapta al ancho sin media queries:
.grilla {display: grid;grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));gap: 12px;}
auto-fill crea tantas columnas como entren: en la demo, 3 de 88px con gap de 12px, y 4 con un gap de 10px o menos. auto-fit hace lo mismo, pero colapsa las columnas que quedan vacías y las celdas se estiran para ocupar la fila. Un detalle: 1fr no se achica por debajo del ancho mínimo de su contenido, como una palabra larga; si necesitás que sí, usá minmax(0, 1fr).
Ubicar elementos
Las columnas están separadas por líneas numeradas desde 1: tres columnas tienen cuatro líneas. También se cuentan desde el final con números negativos, y -1 es la última. grid-column dice entre qué líneas va un elemento, y grid-row hace lo mismo con las filas. Con span indicás cuántas columnas o filas ocupa.
/* de la primera a la última línea: toda la fila */.titulo { grid-column: 1 / -1; }/* dos columnas, desde donde le toque */.destacado { grid-column: span 2; }/* de la línea 1 a la 3: dos filas */.lateral { grid-row: 1 / 3; }
Para el layout de una página, grid-template-areas deja dibujar la grilla con nombres. Cada string es una fila, un nombre repetido ocupa varias celdas y cada elemento elige su área con grid-area. Las áreas tienen que ser rectángulos.
.pagina {display: grid;grid-template-columns: 200px 1fr;grid-template-areas:"cabecera cabecera""lateral contenido";gap: 12px;}.cabecera { grid-area: cabecera; }.lateral { grid-area: lateral; }.contenido { grid-area: contenido; }
En Tailwind
En Tailwind la grilla se arma con clases en el contenedor y en los hijos. Los valores que no están en la escala van entre corchetes, con guiones bajos en lugar de espacios: 200px 1fr se escribe grid-cols-[200px_1fr]. El gap usa la escala de espaciado, donde cada paso vale 4px.
| CSS | Tailwind |
|---|---|
| display: grid | grid |
| repeat(3, minmax(0, 1fr)) | grid-cols-3 |
| 1fr 2fr | grid-cols-[1fr_2fr] |
| gap: 12px · por eje | gap-3 · gap-x-3 · gap-y-3 · gap-[7px] |
| grid-column: span 2 · 1 / -1 | col-span-2 · col-span-full |
| grid-column-start: 2 · end: 4 | col-start-2 col-end-4 |
| grid-row: span 2 · 1 / 3 | row-span-2 · row-start-1 row-end-3 |
<div class="grid grid-cols-[200px_1fr] gap-3[grid-template-areas:'cabecera_cabecera'_'lateral_contenido']"><header class="[grid-area:cabecera]">…</header><aside class="[grid-area:lateral]">…</aside><main class="[grid-area:contenido] grid gap-3grid-cols-[repeat(auto-fill,minmax(64px,1fr))]"><h2 class="col-span-full">Fotos</h2><img class="col-span-2 row-span-2" src="destacada.jpg" alt="" /><img src="1.jpg" alt="" /></main></div>
Grid
Lesson 12 of 37 · 4 min
Grid lays out the children of a box in columns and rows at the same time. You define the columns and the browser shares out the space.
Columns and gap
With display: grid the box becomes a grid, and each direct child takes a cell. Two properties are enough to start:
- Columns
grid-template-columnsThe list of columns, one size per column. Rows are created on their own, as they are needed. - Space
gapThe space between columns and between rows. It only goes between cells, never against the edge of the grid.
Pick a template and move the gap on the café's menu: the orange ruler on top marks each column's width, and the hatching between dishes is the gap.
.menu {display: grid;grid-template-columns: 1fr 1fr 1fr;gap: 12px;}
<ul class="grid grid-cols-3 gap-3"><li>Latte</li><li>Bowl</li><li>Crêpes</li><li>Salmon</li><li>Parfait</li><li>Scone</li></ul>
The grid is 288px wide. With 1fr 1fr 1fr and a 12px gap there are 264px to share, so each column is 88px. The six dishes fill the first row and continue on the second, in order.
The fr unit
fr is a fraction of the free space: what is left after taking away the fixed-size columns and the gaps. The browser adds up the fr and shares the space in proportion. In the 288px grid with a 12px gap:
- Proportion
1fr 2fr276px are left. There are 3fr in total, so the first column gets a third, 92px, and the second two thirds, 184px. - Fixed and flexible
200px 1frThe first column is a fixed 200px and the second takes the rest, 288 − 200 − 12 = 76px.
repeat() saves writing the same thing several times: repeat(3, 1fr) is the same as 1fr 1fr 1fr. minmax() gives a column a minimum and a maximum. Together they build a grid that adapts to its width without media queries:
.grid {display: grid;grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));gap: 12px;}
auto-fill creates as many columns as fit: in the demo, 3 of 88px with a 12px gap, and 4 with a gap of 10px or less. auto-fit does the same, but collapses the columns left empty and the cells stretch to fill the row. One detail: 1fr doesn't shrink below the minimum width of its content, such as a long word; if you need it to, use minmax(0, 1fr).
Placing items
Columns are separated by lines numbered from 1: three columns have four lines. They are also counted from the end with negative numbers, and -1 is the last one. grid-column says which lines an item goes between, and grid-row does the same for rows. With span you say how many columns or rows it takes.
/* from the first to the last line: the whole row */.title { grid-column: 1 / -1; }/* two columns, from wherever it lands */.featured { grid-column: span 2; }/* from line 1 to 3: two rows */.sidebar { grid-row: 1 / 3; }
For a page layout, grid-template-areas lets you draw the grid with names. Each string is a row, a repeated name takes several cells and each item picks its area with grid-area. Areas have to be rectangles.
.page {display: grid;grid-template-columns: 200px 1fr;grid-template-areas:"header header""sidebar content";gap: 12px;}.header { grid-area: header; }.sidebar { grid-area: sidebar; }.content { grid-area: content; }
In Tailwind
In Tailwind the grid is built with classes on the container and on the children. Values that aren't on the scale go in square brackets, with underscores instead of spaces: 200px 1fr is written grid-cols-[200px_1fr]. The gap uses the spacing scale, where each step is 4px.
| CSS | Tailwind |
|---|---|
| display: grid | grid |
| repeat(3, minmax(0, 1fr)) | grid-cols-3 |
| 1fr 2fr | grid-cols-[1fr_2fr] |
| gap: 12px · per axis | gap-3 · gap-x-3 · gap-y-3 · gap-[7px] |
| grid-column: span 2 · 1 / -1 | col-span-2 · col-span-full |
| grid-column-start: 2 · end: 4 | col-start-2 col-end-4 |
| grid-row: span 2 · 1 / 3 | row-span-2 · row-start-1 row-end-3 |
<div class="grid grid-cols-[200px_1fr] gap-3[grid-template-areas:'header_header'_'sidebar_content']"><header class="[grid-area:header]">…</header><aside class="[grid-area:sidebar]">…</aside><main class="[grid-area:content] grid gap-3grid-cols-[repeat(auto-fill,minmax(64px,1fr))]"><h2 class="col-span-full">Photos</h2><img class="col-span-2 row-span-2" src="featured.jpg" alt="" /><img src="1.jpg" alt="" /></main></div>
