Saltar al contenido
schedule 15 min CSS

Flexbox

Antes de flexbox, colocar elementos en horizontal era un infierno de floats, clearfixes y hacks. Hoy, poner 3 cards en fila, centrar un elemento vertical y horizontalmente, o crear una barra de navegación es cuestión de unas pocas líneas. Flexbox cambió CSS para siempre.

El concepto: contenedor y elementos

Flexbox funciona con dos roles:

  • Flex container: el padre al que le pones display: flex.
  • Flex items: los hijos directos del contenedor. Se alinean automáticamente.
<nav class="navbar">
    <a href="/" class="logo">Vinyl Paradise</a>
    <ul class="nav-links">
        <li><a href="#catalogo">Catálogo</a></li>
        <li><a href="#novedades">Novedades</a></li>
        <li><a href="#contacto">Contacto</a></li>
    </ul>
</nav>
.navbar {
    display: flex;
    justify-content: space-between;  /* Logo a la izda, links a la dcha */
    align-items: center;             /* Centrado vertical */
    padding: 1rem 2rem;
    background: #141414;
}

.nav-links {
    display: flex;
    gap: 2rem;                       /* Espacio entre los enlaces */
    list-style: none;
}

Con 5 líneas tienes una barra de navegación que antes requería 20+ líneas de CSS con floats.

Dirección: row vs column

.container {
    display: flex;

    /* En fila — por defecto */
    flex-direction: row;

    /* En columna — los elementos se apilan verticalmente */
    flex-direction: column;

    /* Invertidos */
    flex-direction: row-reverse;
    flex-direction: column-reverse;
}

Cuando usas flex-direction: column, los ejes se intercambian: justify-content afecta al eje vertical y align-items al horizontal.

Justify-content: distribuir en el eje principal

.container {
    display: flex;

    /* Todos al inicio (por defecto) */
    justify-content: flex-start;

    /* Todos al final */
    justify-content: flex-end;

    /* Centrados */
    justify-content: center;

    /* Espacio entre elementos (primero y último pegados a los bordes) */
    justify-content: space-between;

    /* Espacio alrededor de cada elemento */
    justify-content: space-around;

    /* Espacio igual entre y alrededor */
    justify-content: space-evenly;
}

Align-items: alinear en el eje cruzado

.container {
    display: flex;
    min-height: 200px;

    /* Estirar para llenar el contenedor (por defecto) */
    align-items: stretch;

    /* Arriba */
    align-items: flex-start;

    /* Abajo */
    align-items: flex-end;

    /* Centrado vertical */
    align-items: center;

    /* Alinear por la línea base del texto */
    align-items: baseline;
}

El truco del centrado perfecto

/* Centrar cualquier cosa vertical y horizontalmente */
.centered {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100dvh;
}

/* O más corto con place-items (grid es mejor para esto, pero funciona) */
.centered-alt {
    display: grid;
    place-items: center;
    min-height: 100dvh;
}

Gap: espacio entre elementos

.card-grid {
    display: flex;
    gap: 1.5rem;              /* Espacio uniforme */
    gap: 1rem 2rem;           /* row-gap | column-gap */
}

Usa gap en lugar de márgenes en los hijos. No tiene problemas de colapso de márgenes y no necesitas hack de "último elemento sin margen".

Flex-wrap: envolver elementos

Por defecto, flex comprime los elementos para que quepan en una línea. Con flex-wrap: wrap permite que salten a la siguiente línea:

.tags {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.tag {
    padding: 0.25rem 0.75rem;
    background: #222;
    border-radius: 999px;
    font-size: 0.85rem;
}
<div class="tags">
    <span class="tag">Rock</span>
    <span class="tag">Jazz</span>
    <span class="tag">Electrónica</span>
    <span class="tag">Hip Hop</span>
    <span class="tag">Indie</span>
    <span class="tag">Clásica</span>
    <span class="tag">Funk</span>
    <span class="tag">Soul</span>
</div>

Flex-grow, flex-shrink y flex-basis

Estas propiedades van en los hijos (flex items), no en el contenedor:

.sidebar {
    flex-basis: 280px;    /* Ancho inicial */
    flex-shrink: 0;       /* No se encoge */
}

.main-content {
    flex-grow: 1;         /* Ocupa todo el espacio sobrante */
}

/* Shorthand: flex: grow shrink basis */
.sidebar {
    flex: 0 0 280px;     /* No crece, no encoge, base 280px */
}

.main-content {
    flex: 1;             /* Crece para llenar. Equivale a flex: 1 1 0% */
}

Layout típico: sidebar + contenido

.app-layout {
    display: flex;
    min-height: 100dvh;
}

.sidebar {
    flex: 0 0 280px;
    background: #141414;
    padding: 2rem;
}

.content {
    flex: 1;
    padding: 2rem;
}

/* En móvil: apilar verticalmente */
@media (max-width: 768px) {
    .app-layout {
        flex-direction: column;
    }
    .sidebar {
        flex-basis: auto;
    }
}

Order: cambiar el orden visual

/* Mover un elemento al principio sin cambiar el HTML */
.featured-card {
    order: -1;   /* Por defecto todos tienen order: 0 */
}

/* Mover al final */
.newsletter-cta {
    order: 99;
}

Usa order con moderación. Cambiar el orden visual sin cambiar el HTML puede confundir a usuarios de lectores de pantalla, que siguen el orden del DOM.

Align-self: alineación individual

.flex-container {
    display: flex;
    align-items: flex-start;   /* Todos arriba */
}

.special-item {
    align-self: center;        /* Este en concreto, centrado */
}

.push-to-bottom {
    align-self: flex-end;      /* Este, abajo */
}

Patrones comunes con flexbox

Card con footer pegado abajo

.card {
    display: flex;
    flex-direction: column;
    min-height: 300px;
}

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

.card-footer {
    /* Se queda abajo automáticamente */
    padding-block-start: 1rem;
    border-top: 1px solid #222;
}

Lista de acciones alineada a la derecha

.toolbar {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Empujar los botones de acción a la derecha */
.toolbar-actions {
    margin-inline-start: auto;
}
code

Maqueta el catálogo de Vinyl Paradise

Medio schedule 20 min

Construye la página del catálogo de la tienda de vinilos con flexbox:

  • Una .navbar con logo a la izquierda, enlaces centrados y un botón de carrito a la derecha (justify-content: space-between)
  • Un contenedor de tags de género musical con flex-wrap: wrap y gap
  • Una grid de cards de discos (3 por fila) usando flex-wrap: wrap y flex-basis: calc(33.33% - 1rem)
  • Cada card con flex-direction: column y el precio pegado abajo con flex: 1 en el body
  • Un .toolbar con filtros a la izquierda y un botón "Ordenar por" a la derecha con margin-inline-start: auto

No te preocupes por responsive todavía — eso viene en la lección 07.

lightbulb Pistas

Para las cards de 3 en fila, combina flex-wrap: wrap con gap: 1.5rem y dale a cada card flex: 0 0 calc(33.33% - 1rem). En la siguiente lección verás Grid, que es mejor para esto. Pero dominar flexbox primero es fundamental.

Newsletter

Recibe nuevos cursos, actualizaciones, artículos del blog y promociones en tu correo.