Saltar al contenido

CSS, de a poco

Curso de CSS

Layout avanzado

Lección 35 de 37 · 5 min

Grid ya resuelve casi todo. Estas cuatro piezas cubren lo que queda: dibujar el layout con nombres, alinear el interior de tarjetas vecinas, fijar proporciones y apilar elementos de alto distinto sin huecos.

Áreas con nombre

grid-template-areas dibuja la grilla con texto. Cada cadena entre comillas es una fila y cada palabra, una celda. Si repetís un nombre en celdas vecinas, esa área ocupa todas; un punto (.) deja una celda vacía. Después, cada hijo elige su área con grid-area.

css
.receta {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"titulo titulo"
"ingredientes pasos"
"notas pasos";
}
.titulo { grid-area: titulo; }
.pasos { grid-area: pasos; }

Cada área tiene que ser un rectángulo. Una forma de L o un nombre repetido en celdas separadas hace inválida toda la declaración, y la grilla queda sin áreas. Probá las plantillas: el HTML es siempre el mismo y solo cambian las cadenas.

grid-template-areas
1fr 2fr

Receta de locro acomodada en una grilla de 2 columnas y 3 filas, con cada área marcada con su nombre

Locro criollo

4 h · 8 porciones

Ingredientes

  • 500 g de maíz blanco partido
  • 250 g de porotos blancos
  • 500 g de zapallo
  • 300 g de falda
  • 2 chorizos colorados

Preparación

  1. Remojá el maíz y los porotos desde la noche anterior.
  2. Hervilos 2 horas con la falda cortada en cubos.
  3. Sumá el zapallo y los chorizos, y cociná a fuego bajo hasta que espese.

Para servir

Con salsa de pimentón, aceite y cebolla de verdeo.

receta.css
.receta {
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-areas:
"titulo titulo"
"ingredientes pasos"
"notas pasos";
gap: 12px;
}
.titulo { grid-area: titulo; }
.ingredientes { grid-area: ingredientes; }
.pasos { grid-area: pasos; }
.notas { grid-area: notas; }
receta.html
<article class="grid grid-cols-[1fr_2fr] [grid-template-areas:'titulo_titulo'_'ingredientes_pasos'_'notas_pasos'] gap-3">
<header class="[grid-area:titulo]">Locro criollo</header>
<ul class="[grid-area:ingredientes]">…</ul>
<ol class="[grid-area:pasos]">…</ol>
<p class="[grid-area:notas]">Con salsa de pimentón, aceite y cebolla de verdeo.</p>
</article>

Por eso las áreas sirven tanto para el diseño adaptable: en cada media query (o container query) redibujás el mapa y no tocás nada más. Los hijos siguen con su grid-area.

css
.receta {
grid-template-areas: "titulo" "ingredientes" "pasos" "notas";
}
@media (width >= 40rem) {
.receta {
grid-template-columns: 1fr 2fr;
grid-template-areas:
"titulo titulo"
"ingredientes pasos"
"notas pasos";
}
}

Subgrid

Una fila de tarjetas tiene un problema conocido: si un título ocupa dos líneas, todo lo que viene abajo en esa tarjeta baja, y las tarjetas vecinas quedan desparejas. Cada tarjeta es su propia grilla y no sabe nada de las otras.

Con subgrid, la tarjeta no define sus filas: usa las de la grilla madre. Para eso ocupa varias filas de la madre con grid-row: span 3 y declara grid-template-rows: subgrid. Ahora la fila del título mide lo que mide el título más largo, en todas las tarjetas.

La lista usa repeat(auto-fit, minmax(8.5rem, 1fr)): entran tantas columnas de al menos 8.5rem como quepan, y se reparten el sobrante. En un celular quedan dos columnas y la tercera tarjeta baja; subgrid alinea igual las tarjetas de cada banda.

cafés de especialidad…
  • Etiopía Guji

    Durazno, jazmín y té negro. Lavado.

    250 g · $ 16.800

  • Colombia Huila, Finca El Paraíso

    Frutilla y cacao. Fermentación anaeróbica de 72 horas.

    250 g · $ 21.500

  • Brasil Cerrado

    Avellana y dulce de leche.

    250 g · $ 12.900

cafes.css
.cafes {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
gap: 12px;
}
.cafe {
grid-row: span 3; /* ocupa las 3 filas: nombre, notas y precio */
display: grid;
grid-template-rows: subgrid;
row-gap: 6px;
}
cafes.html
<ul class="grid grid-cols-[repeat(auto-fit,minmax(8.5rem,1fr))] gap-3">
<li class="row-span-3 grid grid-rows-subgrid gap-y-1.5">
<h3>Etiopía Guji</h3>
<p>Durazno, jazmín y té negro. Lavado.</p>
<p>250 g · $ 16.800</p>
</li>
…
</ul>

Las líneas naranjas marcan dónde empiezan las notas y el precio. Sin subgrid, los precios igual quedan alineados abajo (la fila del medio tiene 1fr y absorbe la diferencia), pero las notas arrancan a distinta altura. La subgrilla hereda el gap de la madre, salvo que declares el suyo, como hace acá row-gap: 6px.

Funciona igual con columnas (grid-template-columns: subgrid), por ejemplo para alinear etiquetas y campos de un formulario. Subgrid es Baseline ampliamente disponible desde marzo de 2026.

aspect-ratio

aspect-ratio fija la proporción entre ancho y alto. Le das un ancho y el navegador calcula el alto: con 16 / 9 y 256px de ancho, el alto es 144px. Reemplaza al viejo truco de padding-top: 56.25%.

aspect-ratio
256 × 144 px

Foto de portada con aspect-ratio 16 / 9: 256 de ancho por 144 de alto, en píxeles

Bloques de hielo de un glaciar

Crónica · Santa Cruz

Por qué el hielo de los glaciares se ve celeste

portada.css
.portada {
width: 256px;
max-width: 100%;
}
.foto {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
portada.html
<article class="w-64 max-w-full">
<img class="aspect-video w-full object-cover" src="glaciar.webp" alt="Bloques de hielo de un glaciar">
…
</article>

Si la foto no tiene esa proporción, object-fit: cover la recorta para llenar el marco sin deformarla. Y si el contenido no entra en la caja, la caja crece: la proporción es una preferencia, no un límite. Con min-height: 0 o overflow: hidden se mantiene fija.

En un <img> con los atributos width y height, el navegador ya usa esa proporción mientras la imagen carga, así la página no salta.aspect-ratio es Baseline ampliamente disponible.

Masonry: grid-lanes

Masonry es el layout de muro: columnas parejas y elementos de alto distinto, cada uno en la columna que tenga más espacio libre, sin los huecos que deja una grilla. Se discutió años con el nombre de masonry; la sintaxis que quedó es display: grid-lanes, del nivel 3 de Grid.

css
.notas {
display: grid-lanes;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: 12px;
}

Definís las columnas como en grid y el navegador llena los carriles (lanes). Si definís filas en lugar de columnas, el muro es horizontal. La propiedad flow-tolerance decide cuánta diferencia de altura se ignora antes de saltar a otra columna, para que el orden no quede demasiado mezclado.

Todavía no es Baseline: hoy solo lo soporta Safari 26.4. Mientras tanto, el respaldo clásico son las columnas de texto: columns con break-inside: avoid. El resultado se parece, pero el orden va de arriba abajo por columna. Mirá los números naranjas en cada modo.

display
…

Tu navegador todavía no soporta grid-lanes, así que en esa opción ves el respaldo con columnas.

Notas de campo

Reserva Costanera Sur · sábado

  1. 07:05Entramos por Brasil. Niebla sobre la laguna de los Coipos.
  2. 07:20Hornero.
  3. 07:42Pareja de macáes cerca de los juncos. Contamos cuatro pichones arriba del lomo de la hembra.
  4. 08:10Garza blanca.
  5. 08:25Bandada de cotorras sobre los sauces, muy ruidosa.
  6. 08:50Biguá secándose las alas en un tronco caído.
  7. 09:15Picaflor común en las flores del ceibo. Se quedó casi un minuto.
  8. 09:40Salida. 23 especies.
notas.css
/* respaldo para todos: columnas de texto */
.notas {
columns: 8rem;
column-gap: 12px;
}
.nota {
break-inside: avoid;
margin-block-end: 12px;
}
@supports (display: grid-lanes) {
.notas {
display: grid-lanes;
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
gap: 12px;
columns: auto;
}
.nota {
margin-block-end: 0;
}
}
notas.html
<ol class="columns-[8rem] gap-3 supports-[display:grid-lanes]:[display:grid-lanes] supports-[display:grid-lanes]:grid-cols-[repeat(auto-fill,minmax(8rem,1fr))] supports-[display:grid-lanes]:columns-auto">
<li class="break-inside-avoid mb-3 supports-[display:grid-lanes]:mb-0">Entramos por Brasil. Niebla sobre la laguna de los Coipos.</li>
…
</ol>

Con @supports (display: grid-lanes) el mismo CSS sirve en los dos mundos: todos reciben las columnas, y los navegadores que entienden grid-lanes lo pisan. En grid común, cada fila mide lo que mide su nota más alta y quedan los huecos que masonry evita.

En Tailwind

Tailwind tiene clases para subgrid y para las proporciones comunes. Las áreas y grid-lanes no tienen clase propia: van como propiedades arbitrarias entre corchetes, con guiones bajos en lugar de espacios.

CSSTailwind
grid-template-areas[grid-template-areas:'titulo_titulo'_…]
grid-area: pasos[grid-area:pasos]
grid-template-rows: subgridgrid-rows-subgrid
grid-row: span 3row-span-3
repeat(auto-fit, minmax(8.5rem, 1fr))grid-cols-[repeat(auto-fit,minmax(8.5rem,1fr))]
aspect-ratio: 16 / 9aspect-video
aspect-ratio: 1aspect-square
display: grid-lanes[display:grid-lanes]
cafes.html
<ul class="grid grid-cols-[repeat(auto-fit,minmax(8.5rem,1fr))] gap-3">
<li class="row-span-3 grid grid-rows-subgrid gap-y-1.5">
<h3>Etiopía Guji</h3>
<p>Durazno, jazmín y té negro.</p>
<p>250 g · $ 16.800</p>
</li>
</ul>
<ol class="columns-[8rem] gap-3
supports-[display:grid-lanes]:[display:grid-lanes]
supports-[display:grid-lanes]:grid-cols-[repeat(auto-fill,minmax(8rem,1fr))]
supports-[display:grid-lanes]:columns-auto">
<li class="mb-3 break-inside-avoid
supports-[display:grid-lanes]:mb-0">…</li>
</ol>