Skip to content

7. Flexbox

Flexbox (Flexible Box Layout) es un sistema de diseño unidimensional que facilita la distribución de elementos en filas o columnas de manera flexible y eficiente.


Flexbox es un modelo de layout que permite:

  • ✅ Distribuir espacio entre elementos
  • ✅ Alinear elementos fácilmente
  • ✅ Crear layouts responsivos sin media queries
  • ✅ Reordenar elementos visualmente
  • ✅ Manejar tamaños dinámicos
.contenedor {
display: flex; /* Activa Flexbox */
}
/* O en línea */
.contenedor-inline {
display: inline-flex; /* Flexbox inline */
}

Flexbox trabaja con dos ejes perpendiculares:

Eje Principal (Main Axis) y Eje Secundario (Cross Axis)

Section titled “Eje Principal (Main Axis) y Eje Secundario (Cross Axis)”
flex-direction: row (default)
┌─────────────────────────────────────┐
│ │
│ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │
│ │ 1 │ │ 2 │ │ 3 │ │ 4 │ │ ← Cross Axis
│ └────┘ └────┘ └────┘ └────┘ │
│ ────────────────────────────────→ │
│ Main Axis │
└─────────────────────────────────────┘
flex-direction: column
┌─────────────────┐
│ │
│ ┌──────────┐ │ ↓
│ │ 1 │ │ │
│ └──────────┘ │ │
│ ┌──────────┐ │ │ Main Axis
│ │ 2 │ │ │
│ └──────────┘ │ │
│ ┌──────────┐ │ │
│ │ 3 │ │ ↓
│ └──────────┘ │
│ ←───────────→ │
│ Cross Axis │
└─────────────────┘
.contenedor {
display: flex;
flex-direction: row; /* Horizontal (default) → */
flex-direction: row-reverse; /* Horizontal invertido ← */
flex-direction: column; /* Vertical ↓ */
flex-direction: column-reverse; /* Vertical invertido ↑ */
}
.contenedor {
display: flex;
flex-direction: row; /* Horizontal, izquierda a derecha */
}
┌─────────────────────────────┐
│ [1] [2] [3] [4] [5] │
└─────────────────────────────┘

Características:

  • Main Axis: Horizontal →
  • Cross Axis: Vertical ↓
  • Los items se colocan de izquierda a derecha
.contenedor {
display: flex;
flex-wrap: nowrap; /* No envolver (default) */
flex-wrap: wrap; /* Envolver a nuevas líneas */
flex-wrap: wrap-reverse; /* Envolver en orden inverso */
}
.contenedor {
display: flex;
flex-wrap: nowrap; /* Todos en una línea */
}
┌────────────────────────────────────────┐
│ [1] [2] [3] [4] [5] [6] [7] [8] [9] │ ← Todos en una línea
└────────────────────────────────────────┘

⚠️ Los items se encogen para caber

flex-flow - Shorthand para direction y wrap

Section titled “flex-flow - Shorthand para direction y wrap”
/* Forma larga */
.contenedor {
flex-direction: row;
flex-wrap: wrap;
}
/* Forma corta (equivalente) */
.contenedor {
flex-flow: row wrap;
/* direction wrap */
}
/* Ejemplos */
.contenedor {
flex-flow: column nowrap;
flex-flow: row-reverse wrap;
flex-flow: column wrap-reverse;
}

justify-content - Distribuye items en el eje principal

Section titled “justify-content - Distribuye items en el eje principal”

Controla cómo se distribuyen los items a lo largo del main axis.

.contenedor {
display: flex;
justify-content: flex-start; /* Inicio (default) */
justify-content: flex-end; /* Final */
justify-content: center; /* Centro */
justify-content: space-between; /* Espacio entre items */
justify-content: space-around; /* Espacio alrededor */
justify-content: space-evenly; /* Espacio uniforme */
}
.contenedor {
display: flex;
justify-content: flex-start; /* Al inicio */
}
┌─────────────────────────────────────┐
│ [1] [2] [3] │
└─────────────────────────────────────┘

Items alineados al inicio del eje principal


align-items - Alinea items en el eje secundario

Section titled “align-items - Alinea items en el eje secundario”

Controla cómo se alinean los items a lo largo del cross axis (en una sola línea).

.contenedor {
display: flex;
align-items: stretch; /* Estirar (default) */
align-items: flex-start; /* Inicio */
align-items: flex-end; /* Final */
align-items: center; /* Centro */
align-items: baseline; /* Línea base del texto */
}
.contenedor {
display: flex;
align-items: stretch; /* Estira para llenar */
height: 200px;
}
┌─────────────────────────┐
│ ┌───┐ ┌───┐ ┌───┐ │
│ │ 1 │ │ 2 │ │ 3 │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ └───┘ └───┘ └───┘ │
└─────────────────────────┘

Items se estiran para llenar el contenedor (si no tienen height definido)

/* El método más simple para centrar */
.contenedor {
display: flex;
justify-content: center; /* Centrado horizontal */
align-items: center; /* Centrado vertical */
height: 100vh;
}
┌─────────────────────────────┐
│ │
│ │
│ ┌─────────┐ │
│ │Centrado │ │
│ └─────────┘ │
│ │
│ │
└─────────────────────────────┘

align-content - Alinea líneas en el eje secundario

Section titled “align-content - Alinea líneas en el eje secundario”

Controla cómo se distribuyen múltiples líneas en el cross axis (solo funciona con flex-wrap: wrap).

.contenedor {
display: flex;
flex-wrap: wrap; /* Necesario para múltiples líneas */
align-content: stretch; /* Estirar (default) */
align-content: flex-start; /* Inicio */
align-content: flex-end; /* Final */
align-content: center; /* Centro */
align-content: space-between; /* Espacio entre líneas */
align-content: space-around; /* Espacio alrededor */
align-content: space-evenly; /* Espacio uniforme */
}
.contenedor {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
height: 400px;
}
┌─────────────────────────┐
│ [1] [2] [3] [4] │ ← Línea 1
│ [5] [6] [7] │ ← Línea 2
│ │
│ │
│ │
└─────────────────────────┘

Líneas al inicio del contenedor


Sobrescribe align-items para un item específico.

.item {
align-self: auto; /* Hereda de align-items (default) */
align-self: flex-start; /* Al inicio */
align-self: flex-end; /* Al final */
align-self: center; /* Centrado */
align-self: baseline; /* Línea base */
align-self: stretch; /* Estirar */
}
┌─────────────────────────────────┐
│ ┌───┐ ┌───┐ │
│ │ 1 │ │ 3 │ │ ← flex-start
│ └───┘ ┌───┐ └───┘ │
│ │ 2 │ ┌───┐ │
│ │ │ │ 4 │ │ ← center
│ │ │ └───┘ │
│ └───┘ │
│ ┌───┐ │
│ │ 5 │ │ ← flex-end
│ └───┘ │
└─────────────────────────────────┘

Ejemplo:

.contenedor {
display: flex;
align-items: center; /* Todos centrados por defecto */
height: 200px;
}
.item-especial {
align-self: flex-end; /* Este va al final */
}

Define cuánto puede crecer un item para llenar el espacio disponible.

.item {
flex-grow: 0; /* No crece (default) */
flex-grow: 1; /* Crece proporcionalmente */
flex-grow: 2; /* Crece el doble que flex-grow: 1 */
}
.item {
flex-grow: 0; /* Default */
width: 100px;
}
┌─────────────────────────────────────┐
│ [100px] [100px] [100px] (espacio) │
└─────────────────────────────────────┘

Items mantienen su tamaño, espacio sobrante no se usa

Define cuánto puede encogerse un item cuando no hay espacio suficiente.

.item {
flex-shrink: 1; /* Puede encogerse (default) */
flex-shrink: 0; /* No se encoge */
flex-shrink: 2; /* Se encoge el doble */
}
.item {
flex-shrink: 1; /* Todos se encogen igual */
width: 200px;
}
Contenedor pequeño:
┌─────────────────────┐
│ [150] [150] [150] │ ← Todos se encogen
└─────────────────────┘

Todos los items se encogen proporcionalmente

Define el tamaño inicial de un item antes de distribuir el espacio.

.item {
flex-basis: auto; /* Basado en width/height (default) */
flex-basis: 200px; /* Tamaño base fijo */
flex-basis: 50%; /* Porcentaje del contenedor */
flex-basis: 0; /* Sin tamaño base */
}
/* width - Tamaño fijo */
.item-width {
width: 200px;
}
/* flex-basis - Tamaño flexible */
.item-basis {
flex-basis: 200px;
flex-grow: 1; /* Puede crecer desde 200px */
}

flex - Shorthand para grow, shrink y basis

Section titled “flex - Shorthand para grow, shrink y basis”
/* Sintaxis: flex: grow shrink basis */
/* Valores comunes */
.item {
flex: 0 1 auto; /* Default (no crece, sí encoge, auto) */
flex: 1; /* = 1 1 0 (crece, encoge, sin base) */
flex: auto; /* = 1 1 auto (flexible completo) */
flex: none; /* = 0 0 auto (inflexible) */
}
/* flex: 1 - Más usado ⭐ */
.item {
flex: 1;
/* = flex-grow: 1, flex-shrink: 1, flex-basis: 0 */
/* Items de igual tamaño, flexibles */
}
/* flex: auto - Flexible basado en contenido */
.item {
flex: auto;
/* = flex-grow: 1, flex-shrink: 1, flex-basis: auto */
/* Crece/encoge desde su tamaño natural */
}
/* flex: none - Inflexible */
.item {
flex: none;
/* = flex-grow: 0, flex-shrink: 0, flex-basis: auto */
/* Tamaño fijo, no cambia */
}
/* flex: 0 0 200px - Tamaño fijo específico */
.item {
flex: 0 0 200px;
/* No crece, no encoge, 200px fijo */
}

Controla el orden de aparición de los items sin cambiar el HTML.

.item {
order: 0; /* Default - orden del HTML */
order: 1; /* Aparece después */
order: -1; /* Aparece antes */
}
/* HTML: <div>1</div><div>2</div><div>3</div> */
.item-1 { order: 0; } /* Default */
.item-2 { order: -1; } /* Va primero */
.item-3 { order: 2; } /* Va último */
HTML:
[1] [2] [3]
Visual con order:
[2] [1] [3]
↑ ↑ ↑
-1 0 2

Items se ordenan de menor a mayor valor de order


🎨 Layout de página completo con Flexbox
<div style="display: flex; flex-direction: column; height: 400px; border: 2px solid #ccc;">
<header style="flex: 0 0 60px; background: #2c3e50; color: white; display: flex; align-items: center; padding: 0 20px;">
  Header
</header>

<div style="display: flex; flex: 1;">
  <aside style="flex: 0 0 200px; background: #34495e; color: white; padding: 20px;">
    Sidebar
  </aside>
  
  <main style="flex: 1; padding: 20px; background: #ecf0f1;">
    Main Content (flexible)
  </main>
</div>

<footer style="flex: 0 0 50px; background: #2c3e50; color: white; display: flex; align-items: center; padding: 0 20px;">
  Footer
</footer>
</div>
🎨 Navbar con Flexbox
<nav style="display: flex; align-items: center; padding: 0 20px; height: 60px; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<div style="flex: 0 0 150px; font-size: 20px; font-weight: bold; color: #2c3e50;">
  Logo
</div>

<div style="display: flex; flex: 1; gap: 20px; justify-content: center;">
  <a href="#" style="padding: 8px 16px; text-decoration: none; color: #333;">Inicio</a>
  <a href="#" style="padding: 8px 16px; text-decoration: none; color: #333;">Productos</a>
  <a href="#" style="padding: 8px 16px; text-decoration: none; color: #333;">Contacto</a>
</div>

<div style="display: flex; flex: 0 0 auto; gap: 10px;">
  <button style="padding: 8px 20px; border-radius: 4px; border: 1px solid #3498db; background: white; color: #3498db; cursor: pointer;">Login</button>
  <button style="padding: 8px 20px; border-radius: 4px; border: none; background: #3498db; color: white; cursor: pointer;">Registro</button>
</div>
</nav>
🎨 Grid de tarjetas responsive con Flexbox
<div style="display: flex; flex-wrap: wrap; gap: 15px; padding: 20px; background: #f5f5f5;">
<div style="flex: 1 1 200px; max-width: 300px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
  <h3 style="margin: 0 0 10px 0;">Tarjeta 1</h3>
  <p style="margin: 0; color: #666;">Contenido de la tarjeta</p>
</div>

<div style="flex: 1 1 200px; max-width: 300px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
  <h3 style="margin: 0 0 10px 0;">Tarjeta 2</h3>
  <p style="margin: 0; color: #666;">Contenido de la tarjeta</p>
</div>

<div style="flex: 1 1 200px; max-width: 300px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
  <h3 style="margin: 0 0 10px 0;">Tarjeta 3</h3>
  <p style="margin: 0; color: #666;">Contenido de la tarjeta</p>
</div>

<div style="flex: 1 1 200px; max-width: 300px; padding: 20px; background: white; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
  <h3 style="margin: 0 0 10px 0;">Tarjeta 4</h3>
  <p style="margin: 0; color: #666;">Contenido de la tarjeta</p>
</div>
</div>

<p><strong>Observa:</strong> Las tarjetas se adaptan automáticamente al ancho disponible (flex: 1 1 200px).</p>
🎨 Centrado perfecto de modal con Flexbox
<div style="position: relative; height: 300px; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center;">
<div style="background: white; padding: 30px; border-radius: 12px; max-width: 400px; width: 90%; box-shadow: 0 4px 20px rgba(0,0,0,0.3);">
  <h3 style="margin: 0 0 15px 0;">Modal Centrado</h3>
  <p style="margin: 0 0 20px 0; color: #666;">Este modal está perfectamente centrado vertical y horizontalmente con Flexbox.</p>
  <button style="padding: 10px 20px; background: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer;">Cerrar</button>
</div>
</div>

<p><strong>Clave:</strong> display: flex + justify-content: center + align-items: center</p>
🎨 Holy Grail Layout - Header, 3 columnas, Footer
<div style="display: flex; flex-direction: column; height: 400px; border: 2px solid #ccc;">
<header style="flex: 0 0 auto; background: #333; color: white; padding: 15px; text-align: center;">
  Header
</header>

<div style="display: flex; flex: 1;">
  <aside style="flex: 0 0 150px; background: #f0f0f0; padding: 15px; order: 1;">
    Sidebar Left
  </aside>
  
  <main style="flex: 1; padding: 20px; background: white; order: 2;">
    Main Content (flexible)
  </main>
  
  <aside style="flex: 0 0 150px; background: #f0f0f0; padding: 15px; order: 3;">
    Sidebar Right
  </aside>
</div>

<footer style="flex: 0 0 auto; background: #333; color: white; padding: 15px; text-align: center;">
  Footer
</footer>
</div>

<p><strong>Holy Grail:</strong> Layout clásico con header, 3 columnas (sidebar izq + main + sidebar der), y footer.</p>

🐝