README · by ansango
← Volver al libro

Grid Layout

El modelo de layout bidimensional. Cómo crear grids complejos con filas y columnas, áreas nombradas, alineamiento y el truco del subgrid

~1 min de lectura
Resumen

Esta nota cubre el capítulo 12 del libro: CSS Grid Layout, el modelo de layout bidimensional. Permite crear grids complejos con filas y columnas, áreas nombradas, alineamiento y el reciente truco del subgrid. La herramienta principal para layouts de página completos.

Por qué grid

Flexbox es unidimensional: una fila o una columna. Grid es bidimensional: filas y columnas a la vez.

Flexbox vs Grid:

  Flexbox:  [item1] [item2] [item3]
  Grid:     ┌─────┬─────┬─────┐
            │item1│item2│item3│
            ├─────┼─────┼─────┤
            │item4│item5│item6│
            └─────┴─────┴─────┘
Usa grid para:

  - Layouts de página completos.
  - Grids complejos (tipo Excel).
  - Cuando necesitas alinear en ambas dimensiones.
  - Layouts que cambian mucho entre breakpoints.

Usa flexbox para:

  - Componentes: navbars, cards, listas.
  - Cuando solo necesitas una dimensión.
  - Distribuir space entre items.

Conceptos básicos

.container {
    display: grid;
}
Conceptos:

  - Grid container: el padre con display: grid.
  - Grid items: los hijos directos.
  - Grid lines: las líneas que separan filas y columnas.
  - Grid tracks: las filas y columnas.
  - Grid cells: la intersección de una fila y columna.
  - Grid areas: regiones rectangulares del grid.
        col1    col2    col3
        ├───────┼───────┼───────┤
row 1   │  cell │  cell │  cell │
        ├───────┼───────┼───────┤
row 2   │  cell │  cell │  cell │
        └───────┴───────┴───────┘

grid-template-columns y grid-template-rows

.container {
    display: grid;
    grid-template-columns: 100px 200px 100px;
    grid-template-rows: 50px 100px;
}
grid-template-columns:

  - Define el número y tamaño de las columnas.
  - Tres columnas: 100px, 200px, 100px.
  - grid-template-rows: análogo para filas.

Valores:

  - length: 100px, 50%, 1fr.
  - fr: fracción del espacio sobrante.
  - auto: según el contenido.
  - min-content, max-content: según el contenido.

La unidad fr

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;  /* 3 columnas iguales */
    grid-template-columns: 1fr 2fr;       /* segunda el doble */
    grid-template-columns: 200px 1fr;      /* fija + flexible */
}
fr:

  - Fracción del espacio sobrante.
  - 1fr 1fr 1fr: tres columnas iguales.
  - 1fr 2fr: la segunda el doble.
  - El espacio se distribuye DESPUÉS de los tamaños fijos.

repeat()

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-columns: repeat(auto-fill, 200px);
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
repeat():

  - repeat(n, pattern): repite n veces.
  - auto-fill: tantas columnas como quepan.
  - auto-fit: igual, pero colapsa si no hay items.

minmax()

.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
minmax(min, max):

  - Define un rango de tamaño.
  - minmax(200px, 1fr): mínimo 200px, máximo 1fr.
  - Combinado con auto-fit/auto-fill: responsive grid.
  - El grid más común en producción.

gap

.container {
    display: grid;
    gap: 1rem;           /* ambos ejes */
    gap: 1rem 2rem;      /* row | column */
    row-gap: 1rem;
    column-gap: 2rem;
}
gap en grid:

  - Espacio entre filas y columnas.
  - row-gap: espacio entre filas.
  - column-gap: espacio entre columnas.
  - Moderno, reemplaza los margin negativos.

Posicionar items

Líneas y áreas

.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 100px 100px;
}

.item-1 {
    grid-column: 1 / 3;       /* ocupa columnas 1 a 2 */
    grid-row: 1;               /* solo fila 1 */
}

.item-2 {
    grid-column: 3;
    grid-row: 1 / 3;
}
Posición por líneas:

  - grid-column: 1 / 3: de línea 1 a línea 3 (excluyendo).
  - grid-row: 1: solo línea 1.
  - grid-column: span 2: ocupa 2 columnas.

Área nombrada

.container {
    display: grid;
    grid-template-columns: 1fr 3fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "header header"
        "sidebar main"
        "footer footer";
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
grid-template-areas:

  - Define un mapa visual.
  - Usar comillas para cada fila.
  - Nombres separados por espacio.
  - "." para celdas vacías.
  - Cada item se posiciona con grid-area: <nombre>.

Visualización

┌─────────────────────────────────┐
│            header              │
├─────────┬───────────────────────┤
│         │                       │
│ sidebar │         main            │
│         │                       │
├─────────┴───────────────────────┤
│            footer              │
└─────────────────────────────────┘

Grid placement

/* Por línea */
.item-1 {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 2;
}

/* Shorthand */
.item-1 {
    grid-column: 1 / 3;       /* start / end */
    grid-row: 1 / 2;
}

/* Span */
.item-1 {
    grid-column: span 2;       /* ocupa 2 columnas */
}

/* Por área */
.item-1 {
    grid-area: header;          /* usa el área nombrada */
}
El ASCII art es tu amigo

El libro recomienda: dibujar el grid en ASCII antes de escribir el CSS. Cada carácter es una celda. Es mucho más claro que los números.

Grid auto-placement

Cuando no specifies posición, grid coloca los items automáticamente:

.container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1em;
}

/* Los items se colocan en orden, llenando filas */
Auto-placement:

  - grid-row y grid-column: auto.
  - grid-auto-flow: row (default) o column.
  - dense: rellena huecos.
  - Control fino del auto-placement.

grid-auto-flow

.container {
    grid-auto-flow: row;        /* default */
    grid-auto-flow: column;
    grid-auto-flow: row dense;
    grid-auto-flow: column dense;
}
grid-auto-flow:

  - row: filas, llenando izquierda a derecha.
  - column: columnas, llenando arriba a abajo.
  - dense: rellena huecos (puede reordenar).
  - sparse (default): deja huecos.

Alignment

.container {
    display: grid;
    justify-items: center;     /* horizontal en cada celda */
    align-items: center;       /* vertical en cada celda */
    place-items: center;       /* ambos */
    
    justify-content: center;   /* grid completo en el contenedor */
    align-content: center;     /* grid completo en el contenedor */
    place-content: center;     /* ambos */
}
justify-items:

  - Cómo se alinea el item en su celda (horizontal).
  - stretch (default), start, center, end.

align-items:

  - Cómo se alinea el item en su celda (vertical).
  - Igual que justify-items pero vertical.

justify-content:

  - Cómo se alinea el grid completo en el contenedor.
  - stretch, start, center, end, space-between, etc.

align-content:

  - Cómo se alinea el grid completo en el contenedor.
  - Vertical (si hay varias filas).

align-self y justify-self

.item-1 {
    align-self: center;       /* vertical dentro de la celda */
    justify-self: end;        /* horizontal dentro de la celda */
}
Align-self / justify-self:

  - Sobreescribe align-items / justify-items.
  - Solo para el item específico.

Implicit grid

Cuando un item se sale del grid explícito:

.container {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-auto-rows: 100px;      /* filas implícitas */
}

.item-3 {
    grid-column: 1;
    grid-row: 5;                /* fila no definida */
    /* Crea una fila implícita de 100px */
}
Implicit grid:

  - grid-auto-rows: tamaño de filas automáticas.
  - grid-auto-columns: tamaño de columnas automáticas.
  - grid-auto-flow: cómo se colocan las nuevas filas/columnas.

Subgrid

Una de las adiciones más esperadas:

.parent {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
}

.child {
    display: grid;
    grid-template-columns: subgrid;  /* hereda las columnas del padre */
}

.grandchild {
    grid-column: 2;  /* la segunda columna del padre */
}
subgrid:

  - El elemento hereda las columnas/filas del padre.
  - No necesita redefinir el grid.
  - El item se posiciona en las líneas del padre.
  - Útil para componentes anidados.
Subgrid es moderno

El libro destaca: subgrid es relativamente nuevo. Soportado en navegadores modernos, pero no universal. Úsalo si puedes permitirte el soporte.

Repeat y auto-fit

/* El grid responsive más común */
.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1em;
}
Explicación:

  - auto-fit: tantas columnas como quepan.
  - minmax(250px, 1fr): cada columna entre 250px y 1fr.
  - Si caben 4 cards: 4 columnas.
  - Si caben 2: 2 columnas.
  - Si no caben 1: 1 columna (250px).
  - Sin media queries.

Ejemplo típico: layout de página

.page {
    display: grid;
    grid-template-rows: auto 1fr auto;
    grid-template-columns: 1fr;
    min-height: 100vh;
}

.header {
    grid-row: 1;
}

.main {
    grid-row: 2;
}

.footer {
    grid-row: 3;
}
Layout de página:

  - Header: altura automática.
  - Main: ocupa el espacio sobrante.
  - Footer: abajo.
  - 100vh: ocupa toda la pantalla.

Ejemplo típico: 12 columnas

.container {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 1em;
}

.col-6 {
    grid-column: span 6;
}

.col-4 {
    grid-column: span 4;
}

.col-3 {
    grid-column: span 3;
}
Grid de 12 columnas:

  - Patrón típico de frameworks CSS.
  - Cada "col-N" ocupa N columnas.
  - El gap entre columnas.
  - Fácil de combinar.

Grid + Flexbox

.card {
    display: grid;
    grid-template-rows: auto 1fr auto;
    gap: 1em;
}

.card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.card-body {
    /* contenido */
}

.card-footer {
    display: flex;
    justify-content: flex-end;
    gap: 0.5em;
}
Grid + Flexbox:

  - Grid para el layout de página.
  - Flexbox para los componentes.
  - Cada herramienta para lo que es buena.
  - El libro recomienda esta combinación.

Errores comunes

/* Mal: grid sin template */
.container {
    display: grid;
    /* sin grid-template-columns */
    /* el grid es auto, sin estructura */
}

/* Mejor */
.container {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}

/* Mal: items sin posicionamiento */
.item {
    /* cada item se queda en auto-placement */
    /* puede no ser lo que quieres */
}

/* Mejor: usar áreas nombradas */
.container {
    grid-template-areas: "header header" "sidebar main";
}

Grid template areas: dibujo

Dibuja tu grid en ASCII antes de escribir CSS:

  ┌──────┬───────────────┐
  │      │               │
  │ nav  │    content     │
  │      │               │
  └──────┴───────────────┘

Equivale a:

  grid-template-areas:
    "nav    content"
    "nav    content";

Resumen en tres frases

Próximos pasos