Flexbox-altura

 

Conceptos Fundamentales

1. Flexbox - El contenedor padre

Cuando quieres elementos uno al lado del otro, necesitas un contenedor padre con display: flex:

css
.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

text
┌─────────┐  ┌──────────┐
│Header   │  │Header    │
├─────────┤  ├──────────┤
│Body     │  │Body      │
│         │  │Body      │
├─────────┤  │Body      │
│Footer   │  ├──────────┤
└─────────┘  │Footer    │
             └──────────┘
¡No alineados!

3. Solución: Estructura de 3 partes con Flex

css
.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:

text
┌─────────────────┐  ┌─────────────────┐
│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

PropiedadValorExplicación
display: flex-Activa Flexbox
flex-directioncolumnApila elementos verticalmente
flex: 1-El elemento ocupa el espacio disponible
flex-shrink: 0-El elemento NO se encoge
align-items: stretchstretchEn 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:

css
/* 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:

css
/* 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

css
.card {
    margin: 0 auto;  /* Centra individualmente, no alinea */
}

✅ Correcto: Centrar el contenedor, no las tarjetas

css
.contenedor {
    justify-content: center;  /* Centra todo el grupo */
}

❌ Error 2: No usar flex-direction: column

css
.card {
    display: flex;  /* Por defecto es row (horizontal) */
}

✅ Correcto: Especificar dirección

css
.card {
    display: flex;
    flex-direction: column;  /* Apilar verticalmente */
}

❌ Error 3: No usar flex: 1 en el body

css
.card-body {
    /* Sin flex: 1, no se expande */
}

✅ Correcto: Hacer el body elástico

css
.card-body {
    flex: 1;  /* Ocupa el espacio disponible */
}

8. Visualización con colores (para depurar)

Cuando tengas dudas, añade colores temporales:

css
.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

  1. Para alinear horizontalmente: Contenedor padre con display: flex

  2. Para que todas tengan misma altura: align-items: stretch (por defecto)

  3. Para que header/footer no se muevan: flex-shrink: 0

  4. Para 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:

css
.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

css
.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:

text
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:

css
flex-grow: 1;    /* Puede crecer */
flex-shrink: 1;  /* Puede encogerse */
flex-basis: 0%;  /* Punto de partida desde 0 */

Ejemplo visual:

text
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

css
/* 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:

  1. Contenedor .cards-container con align-items: stretch le dice a cada tarjeta: "tú vas a tener la altura del elemento más alto de esta fila"

  2. Cada tarjeta recibe esa altura máxima

  3. 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: 1 ocupa TODO el espacio restante

Fórmula:

text
Altura body = Altura total tarjeta - altura header - altura footer

5. Ejemplo visual con números

Supongamos que la tarjeta más alta tiene 400px:

text
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

PropiedadValores comunesEfecto en altura
align-itemsstretch (default)Hijos ocupan toda la altura del contenedor
align-itemsflex-startHijos toman altura de su contenido (arriba)
align-itemscenterHijos 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

css
/* ❌ 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?

  1. flex-wrap: wrap con flex-direction: column creaba un comportamiento inesperado

  2. Sin flex: 1 en body, el body no se expandía

  3. Cada tarjeta tenía la altura de su contenido, no la del contenedor

css
/* ✅ 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:

html
<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:

  1. Cambia align-items a flex-start → verás que las tarjetas ya no tienen misma altura

  2. Quita flex: 1 del body → verás que el body no se expande

  3. Agrega height: 400px al contenedor → verás cómo las tarjetas se adaptan

  4. Cambia flex-shrink: 0 a flex-shrink: 1 en header/footer → verás cómo se encogen


9. Reglas de oro para dominar altura en Flexbox

  1. Para que todos los hijos tengan misma alturaalign-items: stretch en el padre

  2. Para que un elemento ocupe espacio restanteflex: 1 en ese elemento

  3. Para evitar que algo se encojaflex-shrink: 0

  4. Para apilar verticalmenteflex-direction: column

  5. No mezcles flex-wrap en el mismo nivel que flex-direction: column a 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

Entradas más populares de este blog

Tutorial de CSS: De Cero a Estilizar tu Primera Página Web

layouts

layout-card