introducción

1. Flexbox vs CSS Grid

Antes de aprender cada sistema por separado, es importante entender cuándo usar cada uno. No son alternativas excluyentes: se usan juntos en casi todo proyecto profesional.

📦 Flexbox — Una dimensión
/*
  Ideal para:
  - Barras de navegación
  - Listas horizontales o verticales
  - Alinear elementos dentro de un componente
  - Centrar cosas (vertical + horizontal)
  - Componentes pequeños

  Piensa en Flexbox como
  una línea de elementos.
*/

.nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
🗺 CSS Grid — Dos dimensiones
/*
  Ideal para:
  - Layout de página completo
  - Galerías de imágenes
  - Dashboards con múltiples áreas
  - Cuando necesitas controlar
    filas Y columnas al mismo tiempo

  Piensa en Grid como
  una tabla o cuadrícula.
*/

.pagina {
  display: grid;
  grid-template-areas:
    "header"
    "main"
    "footer";
}

Regla práctica: ¿Necesitas controlar solo una dirección (horizontal o vertical)? → Flexbox. ¿Necesitas controlar ambas a la vez? → CSS Grid. ¿No estás seguro? En la práctica, Grid para el layout exterior y Flexbox para los componentes interiores.

flexbox

2. Flexbox

Flexbox se activa con display: flex en el elemento contenedor. A partir de ese momento, sus hijos directos se convierten en ítems flex y pueden alinearse, distribuirse y redimensionarse de manera flexible.

flex-direction — dirección del eje principal

Define si los ítems se colocan en fila o en columna.

flex-direction: row (default)
A
B
C
flex-direction: row-reverse
A
B
C
flex-direction: column
A
B
C
flex-direction: column-reverse
A
B
C
/* flex-direction controla el eje principal */
.contenedor {
  display: flex;
  flex-direction: row;           /* → izquierda a derecha (default) */
  /* flex-direction: row-reverse;   → derecha a izquierda */
  /* flex-direction: column;        → arriba a abajo */
  /* flex-direction: column-reverse;→ abajo a arriba */
}

justify-content — alineación en el eje principal

Controla cómo se distribuye el espacio a lo largo del eje principal (en row: horizontal).

flex-start
1
2
3
center
1
2
3
flex-end
1
2
3
space-between
1
2
3
space-around
1
2
3
space-evenly
1
2
3
/*
  justify-content distribuye el espacio en el eje principal.
  (Eje horizontal cuando flex-direction: row)
*/
.contenedor {
  display: flex;
  justify-content: flex-start;    /* elementos al inicio */
  /* justify-content: flex-end;      elementos al final */
  /* justify-content: center;        centrados */
  /* justify-content: space-between; espacio entre elementos */
  /* justify-content: space-around;  espacio alrededor */
  /* justify-content: space-evenly;  espacio exactamente igual */
}

align-items — alineación en el eje cruzado

Controla la alineación perpendicular al eje principal (en row: vertical).

align-items: flex-start
tall
med
short
align-items: center
tall
med
short
align-items: flex-end
tall
med
short
align-items: stretch (default)
A
B
C
/*
  align-items controla el eje cruzado (vertical cuando flex-direction: row).
  stretch es el valor por defecto: los ítems se estiran para llenar el contenedor.
*/
.contenedor {
  display: flex;
  align-items: stretch;     /* estira los ítems (default) */
  /* align-items: flex-start;  al inicio del eje cruzado */
  /* align-items: flex-end;    al final del eje cruzado */
  /* align-items: center;      centrados en el eje cruzado */
  /* align-items: baseline;    alineados por la línea base del texto */
}

flex-wrap — envolver ítems

Por defecto los ítems intentan caber en una sola línea. flex-wrap: wrap permite que salten a la siguiente fila.

flex-wrap: nowrap (default) — los ítems se comprimen
ítem 1
ítem 2
ítem 3
ítem 4
ítem 5
ítem 6
flex-wrap: wrap — los ítems saltan de línea
ítem 1
ítem 2
ítem 3
ítem 4
ítem 5
ítem 6
/* flex-wrap controla si los ítems se quedan en una línea o saltan */
.contenedor {
  display: flex;
  flex-wrap: nowrap;    /* todos en una línea (default) */
  /* flex-wrap: wrap;      saltan a la siguiente fila */
  /* flex-wrap: wrap-reverse; saltan hacia arriba */
}

flex — grow, shrink y basis

La propiedad flex es el shorthand de tres propiedades que controlan cómo cada ítem crece, encoge y cuál es su tamaño base.

flex: 1 | flex: 2 | flex: 3 — distribución proporcional
flex: 1
flex: 2
flex: 3
flex: 0 0 120px — tamaño fijo (no crece, no encoge)
120px fijo
flex: 1 (crece)
120px fijo
/*
  flex: grow shrink basis
  ├── flex-grow:   cuánto puede CRECER (0 = no crece)
  ├── flex-shrink: cuánto puede ENCOGER (0 = no encoge)
  └── flex-basis:  tamaño BASE antes de distribuir espacio libre

  Valores comunes:
*/
.item-igual    { flex: 1; }          /* todos iguales → flex: 1 1 0% */
.item-doble    { flex: 2; }          /* el doble de espacio */
.item-fijo     { flex: 0 0 200px; }  /* siempre 200px, no cambia */
.item-auto     { flex: 1 1 auto; }   /* crece y encoge desde su tamaño natural */

align-self y order — propiedades del ítem

align-self — cada ítem puede sobrescribir align-items
default
center
flex-end
stretch
order — cambia el orden visual sin tocar el HTML
HTML: 1 → order: 3
HTML: 2 → order: 1
HTML: 3 → order: 2
/* Propiedades que van en los ÍTEMS, no en el contenedor */

/* align-self sobrescribe align-items solo para ese ítem */
.item-especial {
  align-self: center;     /* flex-start | flex-end | center | stretch | baseline */
}

/* order cambia el orden visual (default: 0 para todos) */
/* valores negativos van primero, positivos van al final */
.primero-visual { order: -1; }
.ultimo-visual  { order: 10; }
/* Importante: no afecta el orden del DOM ni la accesibilidad */
css grid

3. CSS Grid

CSS Grid se activa con display: grid. A diferencia de Flexbox, permite definir una cuadrícula de filas y columnas y colocar los elementos en posiciones exactas dentro de ella.

grid-template-columns — definir columnas

repeat(3, 1fr) — 3 columnas iguales
1
2
3
4
5
6
200px 1fr 2fr — columnas de distinto tamaño
200px
1fr
2fr
repeat(auto-fill, minmax(120px, 1fr)) — columnas automáticas
A
B
C
D
E
/*
  Formas de definir columnas:
*/
.grid {
  display: grid;

  /* Tres columnas fijas de 200px */
  grid-template-columns: 200px 200px 200px;

  /* Tres columnas iguales que ocupan el espacio disponible */
  grid-template-columns: repeat(3, 1fr);

  /* Columnas de distinto tamaño */
  grid-template-columns: 200px 1fr 2fr;

  /* Columnas automáticas RESPONSIVE sin media queries */
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  /*
    auto-fill → crea tantas columnas como quepan
    minmax(200px, 1fr) → mínimo 200px, máximo 1 fracción
    Esto crea un grid que se adapta solo al viewport.
  */
}

grid-template-rows — definir filas

grid-template-rows: 60px 100px 40px
60px
60px
60px
100px
100px
100px
40px
40px
40px
/*
  grid-template-rows funciona igual que columns,
  pero para las filas.
*/
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 60px 100px 40px;  /* fila 1, 2 y 3 */

  /* grid-auto-rows: 80px; → todas las filas generadas automáticamente miden 80px */
}

grid-column y grid-row — spanning

Un ítem puede ocupar más de una celda usando span o especificando las líneas de inicio y fin.

Ítems que ocupan varias celdas
col span 2
normal
normal
row span 2
normal
col span 2
span 4 (toda la fila)
/*
  Los ítems pueden ocupar múltiples celdas con span.
  Las líneas del grid se numeran desde 1.
  Una grilla de 4 columnas tiene 5 líneas verticales (1, 2, 3, 4, 5).
*/
.item-ancho    { grid-column: span 2; }      /* ocupa 2 columnas */
.item-alto     { grid-row:    span 2; }      /* ocupa 2 filas */

/* Especificando líneas exactas: inicio / fin */
.item-preciso  { grid-column: 1 / 4; }      /* de la línea 1 a la 4 (3 columnas) */
.item-exacto   { grid-column: 2 / span 3; } /* empieza en 2, ocupa 3 columnas */
.item-final    { grid-column: 3 / -1; }     /* de columna 3 hasta el final (-1) */

grid-template-areas — nombrar zonas

Esta es la forma más visual y legible de crear layouts. Cada cadena de texto representa una fila, y los nombres definen las áreas.

Layout header / sidebar / main / footer
header
sidebar
main content
/* ── CONTENEDOR: define las áreas y el tamaño de columnas/filas ── */
.layout {
  display: grid;
  grid-template-areas:
    "header  header  header"   /* fila 1: header ocupa toda la fila */
    "sidebar main    main"     /* fila 2: sidebar + main (2 columnas) */
    "footer  footer  footer";  /* fila 3: footer ocupa toda la fila */

  grid-template-columns: 200px 1fr 1fr;   /* ancho de cada columna */
  grid-template-rows: 60px auto 50px;     /* alto de cada fila */
  gap: 1rem;                              /* espacio entre áreas */
}

/* ── ÍTEMS: cada hijo se asigna a su área por nombre ── */
.header  { grid-area: header;  }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main;    }
.footer  { grid-area: footer;  }

/*
  Para hacer el layout responsive, solo hay que cambiar
  grid-template-areas en el media query:
*/
@media (max-width: 600px) {
  .layout {
    grid-template-areas:
      "header"
      "main"
      "sidebar"
      "footer";
    grid-template-columns: 1fr;
  }
}
layout combinado

4. Grid + Flexbox juntos

En un proyecto real, Grid define la estructura general de la página y Flexbox organiza los componentes internos. El siguiente ejemplo muestra cómo conviven.

Contenido principal — display: grid para las cards

📊 Analítica Ver estadísticas
Tareas 12 pendientes
📁 Archivos 42 documentos
💬 Mensajes 3 nuevos
/*
  ESTRUCTURA DE UN LAYOUT REAL
  Grid para la página → Flexbox para los componentes
*/

/* 1. Grid en el body principal */
.pagina {
  display: grid;
  grid-template-areas:
    "header  header"
    "sidebar main"
    "footer  footer";
  grid-template-columns: 200px 1fr;
  grid-template-rows: 60px 1fr 50px;
  min-height: 100vh;
}

/* 2. Flexbox en el header */
.header {
  grid-area: header;
  display: flex;                   /* ← Flexbox aquí */
  justify-content: space-between;
  align-items: center;
}

/* 3. Grid en las cards internas */
.cards {
  display: grid;                   /* ← Grid aquí */
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 1rem;
}

/* 4. Flexbox dentro de cada card */
.card {
  display: flex;                   /* ← Flexbox aquí */
  flex-direction: column;
  gap: 0.5rem;
}
práctica

5. Casos de uso comunes

Navbar con Flexbox

El patrón más común: logo a la izquierda, links centrados o a la derecha, botón al extremo.

/* Navbar clásica con Flexbox */
.navbar {
  display: flex;
  justify-content: space-between;  /* logo | links | botón */
  align-items: center;             /* centrado vertical */
  padding: 1rem 2rem;
}

.nav-links {
  display: flex;                   /* links en fila */
  gap: 1.5rem;
  list-style: none;
}

Centrar perfectamente con Flexbox

La técnica más sencilla para centrar un elemento horizontal y verticalmente.

Centrado perfectamente
justify-content: center + align-items: center
/* La técnica de centrado más limpia en CSS moderno */
.contenedor {
  display: flex;
  justify-content: center;   /* centrado horizontal */
  align-items: center;       /* centrado vertical */
  height: 100vh;             /* necesita altura definida */
}

/* Alternativa con place-items (shorthand) */
.contenedor-v2 {
  display: grid;
  place-items: center;       /* centra en las dos dimensiones */
  height: 100vh;
}

Tarjetas de producto con Flexbox

El truco clave: flex: 1 en la descripción hace que el botón siempre quede al fondo, sin importar el largo del texto.

🌿
Planta Monstera Perfecta para interiores con luz indirecta.
$18.900
Agregar al carrito
📚
CSS Avanzado Libro digital.
$29.000
Agregar al carrito
Café de Especialidad Origen único, tostado en Colombia para un sabor excepcional.
$12.500
Agregar al carrito
/* Tarjeta con botón siempre al fondo */
.card {
  display: flex;
  flex-direction: column;   /* apilado vertical */
}

.card-info {
  flex: 1;                  /* ocupa el espacio libre → empuja el botón abajo */
  display: flex;
  flex-direction: column;
}

.card-descripcion {
  flex: 1;                  /* hace que el precio quede al final de la info */
}

.card-btn {
  /* Este botón siempre queda al fondo de la tarjeta */
  margin-top: auto;
}

Galería con CSS Grid

Grid permite que ciertos elementos ocupen más de una celda, creando layouts asimétricos interesantes.

2
3
4
5
6
7
/* Galería con elemento destacado */
.galeria {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;   /* todas las filas miden 100px por defecto */
  gap: 0.5rem;
}

/* El elemento destacado ocupa 2 columnas y 2 filas */
.destacado {
  grid-column: span 2;
  grid-row:    span 2;
}

Holy Grail Layout con CSS Grid

El clásico layout de tres columnas (header, sidebar izquierdo, contenido central, aside derecho, footer) que era muy difícil antes de Grid.

header
left sidebar
main content
right aside
/* Holy Grail Layout — el layout clásico de 3 columnas */
.pagina {
  display: grid;
  grid-template-areas:
    "header  header   header"
    "left    content  right"
    "footer  footer   footer";
  grid-template-columns: 160px 1fr 120px;
  grid-template-rows: 60px 1fr 50px;
  min-height: 100vh;
}

.header  { grid-area: header;  }
.left    { grid-area: left;    }
.content { grid-area: content; }
.right   { grid-area: right;   }
.footer  { grid-area: footer;  }

/* En móvil, todo en una columna: */
@media (max-width: 600px) {
  .pagina {
    grid-template-areas:
      "header"
      "content"
      "left"
      "right"
      "footer";
    grid-template-columns: 1fr;
  }
}
entregable

6. Proyecto Aplicado

🗺 Dashboard o Portafolio con Grid + Flexbox

Construye una página con un layout completo que demuestre el uso de Flexbox y CSS Grid de forma combinada. Puede ser un dashboard de administración, un portafolio personal o una tienda con sección de productos.

Requisitos mínimos

  • Layout de página completo usando grid-template-areas (header, main, footer mínimo).
  • Navegación horizontal construida con Flexbox y justify-content.
  • Sección de tarjetas o galería usando grid-template-columns: repeat(auto-fill, minmax(...)).
  • Al menos un elemento con grid-column: span N o grid-row: span N.
  • Tarjetas con botón al fondo usando flex-direction: column y flex: 1.
  • Layout responsive: el grid cambia con un media query (de 3 columnas a 1 en móvil).
  • Uso de gap para los espacios (no margin entre ítems).

Criterios de evaluación

📦 Flexbox 25 pts

  • Navbar con justify-content
  • Uso de align-items
  • Tarjetas con flex-direction: column
  • flex: 1 para distribución

🗺 CSS Grid 25 pts

  • Layout con grid-template-areas
  • Galería con auto-fill / minmax
  • Al menos un span de columnas o filas
  • Uso correcto de gap

📱 Responsive 25 pts

  • Mobile First
  • Grid cambia en breakpoints
  • Navbar colapsable en móvil

✨ Calidad 25 pts

  • Código limpio y comentado
  • Uso de variables CSS
  • Sin uso de float ni position para el layout

💡 Herramientas recomendadas: Flexbox Froggy y Grid Garden son juegos interactivos para practicar. El inspector de Chrome/Firefox tiene herramientas visuales para depurar Grid y Flexbox.

Recuerda: No uses float ni position: absolute para construir el layout. Esas técnicas son de generaciones anteriores de CSS. Flexbox y Grid son la forma correcta y moderna.