Apuntes sobre Html2

Cuando uno enseña, dos aprenden.

Flexbox

¿Qué es Flexbox?

Flexbox (Flexible Box Layout) es un sistema de maquetación unidimensional: organiza elementos en una sola dirección, fila o columna. Es la herramienta adecuada cuando quieres distribuir y alinear un conjunto de elementos a lo largo de una línea.

Se activa en el contenedor, que a partir de ese momento se llama flex container. Sus hijos directos pasan a ser flex items y se comportan según las reglas de flexbox.

.contenedor {
    display: flex;
}

Con eso es suficiente para activarlo. Por defecto, los hijos se colocan en fila horizontal, sin saltar de línea, y se encogen si el espacio disponible es insuficiente.

flex-direction: eje principal

Flexbox organiza los elementos a lo largo de un eje principal. flex-direction determina la dirección de ese eje:

.contenedor {
    display: flex;
    flex-direction: row;           /* → fila, de izquierda a derecha (defecto) */
    flex-direction: row-reverse;   /* ← fila invertida */
    flex-direction: column;        /* ↓ columna, de arriba a abajo */
    flex-direction: column-reverse;/* ↑ columna invertida */
}

El eje cruzado es perpendicular al eje principal: si el eje es horizontal (row), el cruzado es vertical, y viceversa. Esta distinción importa para entender justify-content y align-items.

justify-content: distribución en el eje principal

Controla cómo se distribuye el espacio entre los elementos a lo largo del eje principal:

.contenedor {
    display: flex;
    justify-content: flex-start;    /* al inicio (defecto) */
    justify-content: flex-end;      /* al final */
    justify-content: center;        /* centrado */
    justify-content: space-between; /* primero y último pegados a los bordes, espacio entre los demás */
    justify-content: space-around;  /* espacio a ambos lados de cada elemento */
    justify-content: space-evenly;  /* espacio exactamente igual entre todos */
}

space-between es probablemente el más usado en navegación horizontal: el primer elemento se alinea al inicio y el último al final, con el espacio restante repartido entre los demás.

align-items: alineación en el eje cruzado

Controla cómo se alinean los elementos en el eje cruzado (perpendicular al principal):

.contenedor {
    display: flex;
    align-items: stretch;     /* se estiran para ocupar todo el cruzado (defecto) */
    align-items: flex-start;  /* alineados al inicio del eje cruzado */
    align-items: flex-end;    /* alineados al final */
    align-items: center;      /* centrados en el eje cruzado */
    align-items: baseline;    /* alineados por la línea de base del texto */
}

La combinación justify-content: center + align-items: center centra los hijos perfectamente en ambas dimensiones dentro del contenedor. Era notoriamente difícil de conseguir antes de flexbox:

.centrado-perfecto {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;   /* el contenedor ocupa al menos toda la pantalla */
}

flex-wrap: salto de línea

Por defecto, los flex items intentan caber en una sola línea, encogiéndose si es necesario (nowrap). flex-wrap: wrap permite que los elementos salten a la línea siguiente cuando no caben:

.tarjetas {
    display: flex;
    flex-wrap: wrap;
}

.tarjeta {
    width: 300px;  /* cada tarjeta tiene un ancho mínimo deseado */
}

Con flex-wrap: wrap, si no caben tres tarjetas de 300px, la tercera baja a la siguiente línea. Si hay varias líneas, align-content controla cómo se distribuyen entre sí (como justify-content pero para las líneas).

gap: espacio entre elementos

gap añade espacio entre los flex items sin necesidad de márgenes:

.contenedor {
    display: flex;
    gap: 1rem;          /* mismo espacio horizontal y vertical */
    gap: 1rem 2rem;     /* vertical | horizontal */
}

La ventaja sobre los márgenes es que gap solo añade espacio entre elementos, nunca en los bordes exteriores del contenedor. No hay que compensar márgenes del primer o último elemento.

Propiedades en los hijos: flex, align-self, order

Las propiedades vistas hasta ahora se aplican al contenedor. Estas se aplican a cada hijo individualmente:

flex es la propiedad abreviada que combina tres valores: flex-grow (capacidad de crecer), flex-shrink (capacidad de encogerse) y flex-basis (tamaño inicial antes de distribuir el espacio sobrante):

/* flex: grow shrink basis */
.item { flex: 0 0 auto; }   /* no crece, no encoge, tamaño por su contenido */
.item { flex: 1 1 0; }      /* crece y encoge a partes iguales (forma canónica) */
.item { flex: 1; }          /* equivale a flex: 1 1 0 (forma corta) */
.item { flex: 2; }          /* crece el doble que los items con flex: 1 */

Un caso frecuente: una barra con un logo fijo a la izquierda y el resto del espacio para el menú:

.barra {
    display: flex;
    align-items: center;
}
.logo { flex: 0 0 auto; }   /* tamaño fijo, no crece */
.menu { flex: 1; }          /* ocupa todo el espacio restante */

align-self sobreescribe align-items para un hijo concreto:

.contenedor { align-items: center; }
.especial    { align-self: flex-end; }  /* este hijo va al final del eje cruzado */

order cambia el orden visual de los elementos sin alterar el HTML. El valor por defecto es 0; valores menores van antes, mayores van después:

.primero-visual { order: -1; }
.ultimo-visual  { order: 1; }

Patrones frecuentes

Navegación horizontal:

nav ul {
    display: flex;
    list-style: none;
    margin: 0;
    padding: 0;
    gap: 2rem;
    align-items: center;
}

Barra con logo y menú en extremos:

.header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 1rem 2rem;
}

Cuadrícula de tarjetas flexible:

.grid-tarjetas {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
}

.tarjeta {
    flex: 1 1 280px;   /* mínimo 280px, crece si hay espacio */
    max-width: 400px;  /* pero no demasiado */
}

Footer con columnas:

.footer-contenido {
    display: flex;
    gap: 2rem;
    flex-wrap: wrap;
}

.footer-columna {
    flex: 1 1 200px;
}

Recapitulación

  • display: flex convierte un elemento en flex container. Sus hijos directos son flex items.
  • flex-direction define el eje principal: row (horizontal, defecto) o column (vertical).
  • justify-content distribuye el espacio a lo largo del eje principal: flex-start, center, flex-end, space-between, space-around, space-evenly.
  • align-items alinea los elementos en el eje cruzado: stretch (defecto), center, flex-start, flex-end, baseline.
  • flex-wrap: wrap permite que los elementos salten a la siguiente línea cuando no caben.
  • gap añade espacio entre elementos sin márgenes externos. Acepta uno o dos valores (vertical, horizontal).
  • En los hijos: flex: 1 hace que el elemento ocupe espacio proporcional disponible. align-self sobreescribe align-items. order cambia el orden visual.
  • Flexbox es la herramienta para distribución en una dimensión: filas de elementos, barras de navegación, centrado.

Tu proyecto

Reorganiza el <header> con Flexbox para poner el nombre y el nav en la misma línea, y añade una sección de estadísticas rápidas en fila:

header {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 1rem;
}

.stats {
    display: flex;
    gap: 3rem;
    margin-top: 2rem;
}

.stat-numero {
    font-size: 2.5rem;
    font-weight: 600;
    line-height: 1;
}

.stat-etiqueta {
    font-size: 0.8rem;
    color: #888;
    margin-top: 0.25rem;
}
<div class="stats">
  <div>
    <div class="stat-numero">47</div>
    <div class="stat-etiqueta">Proyectos completados</div>
  </div>
  <div>
    <div class="stat-numero">15</div>
    <div class="stat-etiqueta">Años de experiencia</div>
  </div>
</div>

En la próxima lección: CSS Grid: layout bidimensional para crear cuadrículas de proyectos, galerías y estructuras de página complejas.

TOP