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íneas
2. 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 footer
5. 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: 400px
6. 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