Flexbox-altura
Conceptos Fundamentales
1. Flexbox - El contenedor padre
Cuando quieres elementos uno al lado del otro, necesitas un contenedor padre con display: flex:
.contenedor {
display: flex; /* Activa Flexbox */
flex-direction: row; /* Por defecto: horizontal */
}Tu error inicial: Cada tarjeta tenía margin: 0 auto, lo que las centraba individualmente, pero no las ponía en línea.
2. Problema de alturas desiguales
¿Por qué se desalineaban header y footer?
Sin Flexbox, cada tarjeta tiene la altura de su contenido:
Tarjeta "Secretaria": poco contenido → más baja
Tarjeta "Estadísticas": más contenido → más alta
┌─────────┐ ┌──────────┐
│Header │ │Header │
├─────────┤ ├──────────┤
│Body │ │Body │
│ │ │Body │
├─────────┤ │Body │
│Footer │ ├──────────┤
└─────────┘ │Footer │
└──────────┘
¡No alineados!3. Solución: Estructura de 3 partes con Flex
.card {
display: flex;
flex-direction: column; /* Apila verticalmente */
height: 100%; /* Opcional, para altura completa */
}
.card-header {
flex-shrink: 0; /* No se encoge */
}
.card-body {
flex: 1; /* Ocupa el espacio restante */
}
.card-footer {
flex-shrink: 0; /* No se encoge */
}Visualización:
┌─────────────────┐ ┌─────────────────┐ │Header (fijo) │ │Header (fijo) │ ├─────────────────┤ ├─────────────────┤ │ │ │ │ │Body (flexible) │ │Body (flexible) │ │Ocupa lo que sobra │ │Ocupa lo que sobra│ │ │ │ │ ├─────────────────┤ ├─────────────────┤ │Footer (fijo) │ │Footer (fijo) │ └─────────────────┘ └─────────────────┘ ¡Misma altura! ¡Misma altura!
4. Propiedades clave que usamos
| Propiedad | Valor | Explicación |
|---|---|---|
display: flex | - | Activa Flexbox |
flex-direction | column | Apila elementos verticalmente |
flex: 1 | - | El elemento ocupa el espacio disponible |
flex-shrink: 0 | - | El elemento NO se encoge |
align-items: stretch | stretch | En el contenedor, hace que todos los hijos tengan la misma altura |
5. Analogía para entenderlo
Imagina que cada tarjeta es un armario con 3 estantes:
/* Sin Flexbox - armarios de diferentes alturas */
.armario {
/* Cada armario mide lo que miden sus estantes */
}
/* Con Flexbox - todos los armarios iguales */
.armario {
display: flex;
flex-direction: column;
height: 100%; /* Todos miden igual */
}
.estante-superior {
flex-shrink: 0; /* Estante fijo, no se ajusta */
}
.estante-medio {
flex: 1; /* Se estira para llenar el espacio */
}
.estante-inferior {
flex-shrink: 0; /* Estante fijo */
}6. Checklist para futuros proyectos
Cuando quieras tarjetas alineadas:
/* 1. Contenedor padre */
.contenedor {
display: flex;
flex-wrap: wrap; /* Para responsive */
gap: 20px; /* Espacio entre tarjetas */
align-items: stretch; /* MISMA ALTURA (por defecto) */
}
/* 2. Cada tarjeta */
.card {
display: flex;
flex-direction: column; /* Apilar verticalmente */
width: 250px; /* Ancho fijo o porcentaje */
}
/* 3. Partes de la tarjeta */
.card-header,
.card-footer {
flex-shrink: 0; /* No se encogen */
}
.card-body {
flex: 1; /* Ocupa espacio restante */
display: flex; /* Si quieres centrar contenido interno */
align-items: center; /* Centrado vertical */
justify-content: center; /* Centrado horizontal */
}7. Errores comunes que ya no cometerás
❌ Error 1: Poner margin: 0 auto en cada tarjeta
.card {
margin: 0 auto; /* Centra individualmente, no alinea */
}✅ Correcto: Centrar el contenedor, no las tarjetas
.contenedor {
justify-content: center; /* Centra todo el grupo */
}❌ Error 2: No usar flex-direction: column
.card {
display: flex; /* Por defecto es row (horizontal) */
}✅ Correcto: Especificar dirección
.card {
display: flex;
flex-direction: column; /* Apilar verticalmente */
}❌ Error 3: No usar flex: 1 en el body
.card-body {
/* Sin flex: 1, no se expande */
}✅ Correcto: Hacer el body elástico
.card-body {
flex: 1; /* Ocupa el espacio disponible */
}8. Visualización con colores (para depurar)
Cuando tengas dudas, añade colores temporales:
.card-header {
background-color: lightblue; /* Visualiza header */
}
.card-body {
background-color: lightgreen; /* Visualiza body */
}
.card-footer {
background-color: lightcoral; /* Visualiza footer */
}Así verás cómo se distribuye el espacio.
📝 Resumen para recordar
Para alinear horizontalmente: Contenedor padre con
display: flexPara que todas tengan misma altura:
align-items: stretch(por defecto)Para que header/footer no se muevan:
flex-shrink: 0Para que el body ocupe espacio:
flex: 1
Regla mnemotécnica: "Padre flex, hijos column, header y footer fijos, body elástico"
¿Te gustaría que profundice en algún concepto específico o tienes alguna duda?
El problema específico de tu código
Tu código tenía este problema:
.card-uno {
display: flex;
flex-wrap: wrap; /* ← ¡ESTE ES EL CULPABLE! */
flex-direction: column;
}flex-wrap: wrap en un elemento con flex-direction: column causa comportamientos extraños en la altura. Además, te faltaba la propiedad clave para que el body se expanda.
📏 Cómo funciona la altura en Flexbox
1. La diferencia entre align-items y align-content
.contenedor {
display: flex;
flex-wrap: wrap; /* Si hay wrap, cambia el comportamiento */
align-items: stretch; /* Controla cada línea individual */
align-content: stretch; /* Controla cómo se distribuyen las LÍNEAS */
}Visualización:
Sin wrap (una sola línea):
┌────┐ ┌────┐ ┌────┐
│A │ │B │ │C │ ← align-items controla altura
└────┘ └────┘ └────┘
Con wrap (múltiples líneas):
┌────┐ ┌────┐
│A │ │B │ ← Línea 1
└────┘ └────┘
┌────┐
│C │ ← Línea 2
└────┘
↑
align-content controla espacio entre líneas2. La propiedad mágica: flex: 1
flex: 1 es una abreviatura de:
flex-grow: 1; /* Puede crecer */
flex-shrink: 1; /* Puede encogerse */
flex-basis: 0%; /* Punto de partida desde 0 */Ejemplo visual:
Sin flex: 1 en body:
┌─────────────────┐
│Header (altura fija)│
├─────────────────┤
│Body (altura de contenido)│ ← No se expande
├─────────────────┤
│Footer (altura fija)│
└─────────────────┘
Con flex: 1 en body:
┌─────────────────┐
│Header (altura fija)│
├─────────────────┤
│ │
│Body (SE EXPANDE)│ ← Ocupa TODO el espacio
│ │
├─────────────────┤
│Footer (altura fija)│
└─────────────────┘3. Estructura completa para tarjetas iguales
/* CONTENEDOR PADRE */
.cards-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
align-items: stretch; /* ← CLAVE: hace que todas las tarjetas tengan la misma altura */
}
/* CADA TARJETA */
.card-uno {
display: flex;
flex-direction: column; /* Apilar verticalmente */
width: 250px;
/* NO poner height fijo */
}
/* HEADER - fijo */
.card-header {
flex-shrink: 0; /* No se encoge */
/* flex-grow: 0; por defecto, no crece */
}
/* BODY - elástico */
.card-body {
flex: 1; /* Crece para ocupar espacio */
display: flex;
flex-direction: column;
justify-content: center; /* Centra contenido si quieres */
}
/* FOOTER - fijo */
.card-footer {
flex-shrink: 0; /* No se encoge */
margin-top: auto; /* Otra forma de empujar al fondo */
}4. ¿Cómo se calcula la altura?
Paso a paso:
Contenedor
.cards-containerconalign-items: stretchle dice a cada tarjeta: "tú vas a tener la altura del elemento más alto de esta fila"Cada tarjeta recibe esa altura máxima
Dentro de cada tarjeta (que ya tiene altura definida):
Header: altura según su contenido (no se encoge)
Footer: altura según su contenido (no se encoge)
Body: con
flex: 1ocupa TODO el espacio restante
Fórmula:
Altura body = Altura total tarjeta - altura header - altura footer5. Ejemplo visual con números
Supongamos que la tarjeta más alta tiene 400px:
Tarjeta Secretaria (contenido pequeño):
┌─────────────────┐
│Header: 50px │ ← fijo
├─────────────────┤
│ │
│Body: 320px │ ← flex: 1 (se expande a 320px)
│(contenido real │
│ solo 30px) │
│ │
├─────────────────┤
│Footer: 30px │ ← fijo
└─────────────────┘
Total: 400px
Tarjeta Estadísticas (contenido grande):
┌─────────────────┐
│Header: 50px │ ← fijo
├─────────────────┤
│Body: 320px │ ← flex: 1 (también 320px)
│(contenido real │
│ 150px, se expande│
│ para igualar) │
├─────────────────┤
│Footer: 30px │ ← fijo
└─────────────────┘
Total: 400px6. Propiedades clave que debes dominar
| Propiedad | Valores comunes | Efecto en altura |
|---|---|---|
align-items | stretch (default) | Hijos ocupan toda la altura del contenedor |
align-items | flex-start | Hijos toman altura de su contenido (arriba) |
align-items | center | Hijos se centran verticalmente |
flex: 1 | - | Elemento ocupa espacio restante |
flex-shrink: 0 | - | Evita que el elemento se encoja |
min-height: 0 | - | Permite que el contenido overflow funcione |
7. Tu error específico explicado
/* ❌ TU CÓDIGO ANTES */
.card-uno {
display: flex;
flex-wrap: wrap; /* ← Esto interfiere con flex-direction: column */
flex-direction: column;
}
.card-body {
/* No tenía flex: 1 */
}¿Qué pasaba?
flex-wrap: wrapconflex-direction: columncreaba un comportamiento inesperadoSin
flex: 1en body, el body no se expandíaCada tarjeta tenía la altura de su contenido, no la del contenedor
/* ✅ CÓDIGO CORREGIDO */
.card-uno {
display: flex;
flex-direction: column; /* Solo column, sin wrap */
/* flex-wrap se quita o se pone en el contenedor */
}
.card-body {
flex: 1; /* Ahora se expande */
}8. Ejercicio práctico para dominarlo
Prueba este código y cambia los valores para ver qué pasa:
<div class="demo">
<div class="card">
<div class="header">Header (fijo)</div>
<div class="body">Body: Contenido pequeño</div>
<div class="footer">Footer (fijo)</div>
</div>
<div class="card">
<div class="header">Header (fijo)</div>
<div class="body">
Body: Mucho contenido<br>
Línea 2<br>
Línea 3<br>
Línea 4
</div>
<div class="footer">Footer (fijo)</div>
</div>
</div>
<style>
.demo {
display: flex;
gap: 20px;
align-items: stretch; /* Cambia a flex-start, center, etc */
background: #eee;
min-height: 300px; /* Prueba cambiando esto */
}
.card {
display: flex;
flex-direction: column;
width: 200px;
background: white;
}
.header, .footer {
background: #ddd;
padding: 10px;
flex-shrink: 0;
}
.body {
background: #f0f0f0;
padding: 10px;
/* PRUEBA: quita flex:1 y mira qué pasa */
flex: 1;
}
</style>Pruebas que debes hacer:
Cambia
align-itemsaflex-start→ verás que las tarjetas ya no tienen misma alturaQuita
flex: 1del body → verás que el body no se expandeAgrega
height: 400pxal contenedor → verás cómo las tarjetas se adaptanCambia
flex-shrink: 0aflex-shrink: 1en header/footer → verás cómo se encogen
9. Reglas de oro para dominar altura en Flexbox
Para que todos los hijos tengan misma altura:
align-items: stretchen el padrePara que un elemento ocupe espacio restante:
flex: 1en ese elementoPara evitar que algo se encoja:
flex-shrink: 0Para apilar verticalmente:
flex-direction: columnNo mezcles
flex-wrapen el mismo nivel queflex-direction: columna menos que sepas lo que haces
10. Analogía final
Piensa en un edificio de apartamentos:
Contenedor = El edificio (tiene altura definida por el más alto)
align-items: stretch = Todos los apartamentos tienen la misma altura
Cada tarjeta = Un apartamento
Header = Techo fijo (no cambia)
Footer = Piso fijo (no cambia)
Body con flex:1 = El espacio entre techo y piso que se ajusta para llenar todo
Si el apartamento de al lado tiene más altura total, TODOS los apartamentos se estiran a esa altura. Dentro de cada uno, el techo y piso se quedan igual, y la pared del medio (body) se estira para ocupar lo que sobre.
¿Qué parte te gustaría que profundice más? ¿Quieres ver ejemplos con min-height, o cómo manejar contenido que desborda, o tal vez cómo hacerlo responsive?
Comentarios
Publicar un comentario