Apuntes sobre Html2

Cuando uno enseña, dos aprenden.

CSS Grid

¿Qué es CSS Grid?

Grid Layout es un sistema de maquetación bidimensional: permite colocar elementos en filas y columnas simultáneamente. Es la herramienta adecuada para layouts de página, cuadrículas de tarjetas, o cualquier composición que tenga estructura tanto horizontal como vertical.

Al igual que Flexbox, Grid se activa en el contenedor:

.contenedor {
    display: grid;
}

Sin más configuración, el grid coloca los hijos en una sola columna. Para que sea útil, hay que definir las columnas (y opcionalmente las filas).

Definir columnas y filas

grid-template-columns define cuántas columnas tiene el grid y el ancho de cada una. grid-template-rows hace lo mismo para las filas (aunque las filas suelen dejarse en auto para que se ajusten al contenido):

/* Tres columnas: fija, auto, fija */
.contenedor {
    display: grid;
    grid-template-columns: 200px auto 200px;
}

/* Tres columnas del mismo tamaño */
.contenedor {
    display: grid;
    grid-template-columns: 33% 33% 33%;   /* aproximado */
}

/* Dos filas con altura definida */
.contenedor {
    display: grid;
    grid-template-rows: 80px auto;
}

La unidad fr

fr (fracción) representa una parte del espacio disponible después de restar los elementos con tamaños fijos. Es la unidad nativa de Grid:

/* Dos columnas que se reparten el espacio al 50% */
grid-template-columns: 1fr 1fr;

/* Columna lateral fija + contenido principal que ocupa el resto */
grid-template-columns: 250px 1fr;

/* Barra lateral + contenido + barra secundaria (proporciones 1:3:1) */
grid-template-columns: 1fr 3fr 1fr;

La ventaja sobre los porcentajes es que fr respeta los gaps: el espacio entre columnas no afecta al cálculo.

repeat() y minmax()

repeat() evita repetir el mismo valor varias veces:

/* Cuatro columnas iguales */
grid-template-columns: repeat(4, 1fr);

/* Equivale a: 1fr 1fr 1fr 1fr */

minmax(mínimo, máximo) define un rango de tamaño para una columna o fila: no menos del mínimo, no más del máximo:

/* Columnas que nunca son menores de 200px ni mayores de 1fr */
grid-template-columns: repeat(3, minmax(200px, 1fr));

Espacio entre celdas: gap

Funciona igual que en Flexbox: añade espacio entre los elementos del grid sin afectar a los bordes exteriores:

.grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1.5rem;           /* mismo espacio en filas y columnas */
    gap: 1rem 2rem;        /* filas | columnas */
}

Colocación de elementos

Por defecto, los hijos se colocan automáticamente en el grid, uno por celda. Puedes controlar explícitamente dónde va cada elemento y cuántas celdas ocupa:

.elemento {
    grid-column: 1 / 3;   /* desde la línea 1 hasta la línea 3 (ocupa 2 columnas) */
    grid-row: 1 / 2;      /* desde la línea 1 hasta la línea 2 (ocupa 1 fila) */
}

/* Forma alternativa: indicar cuántas celdas se expande */
.elemento {
    grid-column: 1 / span 2;   /* comienza en columna 1, se extiende 2 columnas */
    grid-row: span 2;          /* se extiende 2 filas desde su posición automática */
}

Las líneas del grid se numeran desde 1. También se pueden usar números negativos para contar desde el final: -1 es la última línea, -2 la penúltima, etc.

/* Elemento que ocupa todas las columnas */
.ancho-completo {
    grid-column: 1 / -1;
}

Áreas con nombre: grid-template-areas

La característica más legible de Grid: defines la estructura visual del layout directamente en CSS, como un mapa:

.pagina {
    display: grid;
    grid-template-columns: 250px 1fr;
    grid-template-rows: auto 1fr auto;
    grid-template-areas:
        "header  header"
        "sidebar main"
        "footer  footer";
    min-height: 100vh;
}

/* Asigna cada hijo a su área */
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.footer  { grid-area: footer; }
<div class="pagina">
    <header class="header">...</header>
    <aside class="sidebar">...</aside>
    <main class="main">...</main>
    <footer class="footer">...</footer>
</div>

En la cadena de grid-template-areas, cada fila va entre comillas y los nombres separados por espacios representan las columnas. Un punto (.) significa celda vacía. Las áreas de más de una celda deben formar un rectángulo.

Colocación automática y auto-fit

La combinación de repeat() con auto-fit y minmax() crea cuadrículas responsivas sin media queries: el navegador coloca tantas columnas como quepan:

.galeria {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 1.5rem;
}

En pantallas anchas puede haber 4 o 5 columnas. En móvil, solo 1. Sin una sola media query.

auto-fill es similar pero mantiene columnas vacías si el contenido no las llena. auto-fit colapsa las vacías y estira las que hay. Para la mayoría de usos, auto-fit es el correcto.

Para filas de altura automática que se ajustan al contenido:

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    grid-auto-rows: minmax(150px, auto);   /* mínimo 150px, crece con el contenido */
    gap: 1rem;
}

Flexbox vs Grid: ¿cuándo usar cada uno?

No son excluyentes: se usan juntos, en distintos niveles de la misma página.

Usa Flexbox cuando el layout es principalmente en una dimensión: una barra de navegación, una fila de iconos, un grupo de botones, centrar un elemento en su contenedor.

Usa Grid cuando el layout es bidimensional: la estructura completa de la página, una cuadrícula de tarjetas, un calendario, cualquier composición donde las filas y las columnas deben alinearse entre sí.

Un patrón habitual: Grid para el layout general de la página, Flexbox para los componentes internos (la barra de navegación dentro del header, las acciones dentro de una tarjeta).

Recapitulación

  • display: grid activa CSS Grid en el contenedor. Los hijos directos son grid items.
  • grid-template-columns define el número y ancho de las columnas. grid-template-rows hace lo mismo para las filas.
  • La unidad fr representa una fracción del espacio disponible después de restar tamaños fijos. Es más robusta que los porcentajes con gaps.
  • repeat(N, tamaño) repite una definición N veces. minmax(min, max) define un rango de tamaño.
  • gap añade espacio entre celdas sin afectar a los bordes externos.
  • grid-column y grid-row colocan un elemento en posiciones concretas o lo extienden con span. 1 / -1 ocupa todas las columnas.
  • grid-template-areas permite definir el layout como un mapa visual de nombres. Cada hijo se asigna con grid-area.
  • repeat(auto-fit, minmax(X, 1fr)) crea cuadrículas responsivas sin media queries.
  • Grid es bidimensional (filas y columnas). Flexbox es unidimensional (fila o columna). Se complementan y usan juntos en distintos niveles del layout.

Tu proyecto

Sustituye la tabla de proyectos por una cuadrícula de tarjetas. Cambia el HTML de la sección #proyectos y añade el CSS correspondiente:

<section id="proyectos">
  <h2>Proyectos</h2>
  <div class="grid-proyectos">
    <div class="tarjeta">
      <img src="imagenes/proyecto1.jpg" alt="Vivienda en el Retiro">
      <h3>Vivienda en el Retiro</h3>
      <p>Residencial · Madrid, 2023</p>
    </div>
    <div class="tarjeta">...</div>
    <div class="tarjeta">...</div>
  </div>
</section>
.grid-proyectos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
    gap: 1.5rem;
    margin-top: 1.5rem;
}

.tarjeta img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.tarjeta h3 {
    font-size: 1rem;
    font-weight: 600;
    margin-top: 0.75rem;
}

.tarjeta p {
    font-size: 0.85rem;
    color: #888;
    margin-top: 0.25rem;
}

La cuadrícula se adapta sola al ancho disponible gracias a auto-fit y minmax: en pantalla grande muestra tres columnas, en tablet dos, en móvil una. Sin una sola media query.

En la próxima lección: selectores avanzados: combinadores, pseudoclases de estado y estructura, y selectores de atributo.

TOP