Flex

<< Nesting Para container >>

Flexbox, o "Flexible Box Layout", es un modelo de diseño en CSS que te permite organizar, alinear y distribuir el espacio entre los elementos de un contenedor de una manera predecible y eficiente, incluso cuando su tamaño es desconocido o dinámico. Piensa en ello como un conjunto de herramientas para colocar elementos en una sola dimensión, ya sea en fila o en columna.

Su principal ventaja es que "flexibiliza" los elementos, permitiendo que se expandan para llenar el espacio disponible o se encojan para evitar desbordarse del contenedor. El concepto de flex está pensado para trabajar en una sola dimensión.

Los elementos básicos que tenemos en el esquema de flex son los siguientes:

  • Contenedor: es el elemento padre, tendrá en su interior cada uno de los ítems. Con flex las propiedades se las establecemos al elemento padre.
  •          ◦ Eje principal: Los contenedores tendrán una orientación horizontal (por defecto)
  •          ◦ Eje secundario: Es la orientación alternativa, que será en vertical (por defecto, siendo el eje principal el horizontal).
  • Ítem: Cada uno de los hijos que tiene el contenedor en su interior.

El ejemplo clásico de flex es el típico menú de una web

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
nav {
    display: flex;
    gap: 20px;
    background-color: #700000;
    padding: 1%;

    a {
        text-decoration: none;
        color: white;
    }
}

Para indicar que el contenedor se va a comportar en modo flex usamos la propiedad display : flex (Establece un contenedor en bloque, similar a block, ocupando todo el ancho del padre) o display: inline-flex(Establece un contenedor en línea, similar a inline-block, ocupando sólo lo que ocupa el contenido).

Propiedades para el contenedor padre

display: flex; Este es el primer paso y el más importante. Convierte un elemento en un contenedor flexible y todos sus hijos directos se convierten en elementos flexibles.

flex-direction

Podemos modificar la orientación del eje principal utilizando la propiedad flex-direction. Los valores que podemos usar son: 

  • row (por defecto): Los elementos se apilan horizontalmente.
  • row-reverse: Igual que row, pero en orden inverso.
  • column: Los elementos se apilan verticalmente.
  • column-reverse: Igual que column, pero en orden inverso.

justify-content

Alinea los elementos a lo largo del eje principal. Es ideal para distribuir el espacio sobrante.

  • flex-start (por defecto): Los agrupa al inicio.
  • flex-end: Los agrupa al final.
  • center: Los centra.
  • space-between: Distribuye el espacio uniformemente; el primer elemento está al inicio y el último al final.
  • space-around: Distribuye el espacio uniformemente, pero con la mitad de espacio en los extremos.
  • space-evenly: Distribuye el espacio de manera que la separación entre cualquier par de elementos sea idéntica.

flex-wrap

Lo habitual es utilizar flex para estructuras de una única dimensión, pero tiene la propiedad flex-wrap con la que podemos modificar su comportamiento. Por defecto, si un elemento (ítem) no cabe en el contenedor los elementos que tiene el container se hacen más pequeños para así ajustarlos y que entren todos, pero con la propiedad flex-wrap lo que hacemos es decirle que si no cabe se convierta en un contenedor multilínea. Los valores que puede tener son: 

  • nowrap (por defecto): Todos los elementos en una sola línea.
  • wrap: Los elementos que no quepan pasarán a la línea siguiente.
  • wrap-reverse: Igual que wrap, pero en orden inverso.

(atajo) flex-flow: <flex-direction> <flex-wrap>

Podemos utilizar en lugar de las propiedades flex-direction y flex-wrap la propiedad flex-flow. Esta propiedad nos permite asignar las dos propiedades anteriores de un sólo golpe. flex-flow: <flex-direction> <flex-wrap>. Ver ejemplo aquí.

align-items

Alinea los elementos a lo largo del eje cruzado. (Si el eje principal es horizontal, el cruzado es vertical).

  • stretch (por defecto): Estira los elementos para que ocupen todo el alto (o ancho) del contenedor.
  • flex-start: Los alinea al inicio del eje cruzado.
  • flex-end: Los alinea al final del eje cruzado.
  • center: Los centra en el eje cruzado.

¿Qué diferencia hay entre justify-content y align-items? La diferencia radica en el eje sobre el que actúa cada propiedad. La dirección de estos ejes va a depender de la propiedad flex-direction.

  • Si flex-direction: row (el valor por defecto), el eje principal es horizontal (↔️) y el secundario es vertical (↕️).
  • Si flex-direction: column, el eje principal es vertical (↕️) y el secundario es horizontal (↔️).

Propiedades para los elementos hijos

flex-grow

flex-grow: Define la capacidad de un elemento para "crecer" y ocupar el espacio disponible en el eje principal. Es un número que funciona como una proporción. Si todos tienen 1, el espacio se reparte por igual. Si uno tiene 2 y los demás 1, el primero tomará el doble de espacio que los otros. Su valor por defecto es 0.

flex-shrink

flex-shrink: Define la capacidad de un elemento para "encogerse" si no hay suficiente espacio. Funciona de manera similar a flex-grow. Su valor por defecto es 1

flex-basis

flex-basis: Define el tamaño inicial de un elemento antes de que se distribuya el espacio sobrante. Puede ser un valor en px, %, etc. Su valor por defecto es auto.

(atajo) flex: <flex-grow> <flex-shrink> <flex-basis>

Podemos utilizar en lugar de las propiedades flex-grow, flex-shrink y flex-basis la propiedad flex. Esta propiedad nos permite asignar las tres propiedades anteriores de un sólo golpe. flex: <flex-grow> <flex-shrink> <flex-basis>. Ver ejemplo aquí.

order

order: Permite cambiar el orden visual de los elementos sin modificar el HTML. Por defecto, todos tienen order: 0. Un número menor aparecerá antes.

align-self

align-self: Permite anular el align-items del contenedor para un solo elemento hijo.

row-gap y column-gap

Si queremos que los elementos que contiene el container estén separados entre sí, tenemos las propiedades row-gap(espacio entre filas, sólo funciona con flex-direction: column) y column-gap(espacio entre columnas, sólo funciona con flex-direction: row) que harían la función de padding o margin en los elementos hijos. Sólo una de estas dos propiedades tendrá efecto cuando sea un diseño en una sola dimensión, cuando tengamos la propiedad multilínea(flex-wrap) ahí podremos usar ambas, separando los ítems por filas y columnas.

.container {
      display: flex;
      flex-flow: row wrap-reverse;
      column-gap: 10px;
      row-gap: 10px;
      background: gainsboro;
      width: 200px;

      .item {
            background: green;
            color: white;
      }
}

gap

Como atajo a la propiedad anterior, tenemos la propiedad gap, donde podemos indicar de una sola vez los valores para las propiedades row-gap y column-gap. Si indicamos un solo valor ese valor será aplicado a ambos ejes, en el caso de poner valores distintos (o dos valores) se aplicará el primero de ellos para el ejeX y el segundo para el ejeY.

.container {
      display: flex;
      flex-flow: row wrap-reverse;
      gap: 10px;
      background: gainsboro;
      width: 200px;

      .item {
            background: green;
            color: white;
      }
}

Ejemplo completo

<!DOCTYPE html>
<html lang="es">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Galería Flexbox Completa</title>
    <link rel="stylesheet" href="1. flex.css">
</head>

<body>
    <header>
        <h1>Nuestros Productos</h1>
    </header>


    <main class="galeria-productos">
        <section class="tarjeta-producto">
            <h3>Producto Normal</h3>
            <p>Descripción breve de un producto estándar.</p>
            <button>Ver más</button>
        </section>

        <section class="tarjeta-producto destacada">
            <h3>Producto Destacado</h3>
            <p>Esta tarjeta es especial. Crecerá más que las otras para llamar la atención. Su contenido también está
                alineado de forma diferente.</p>
            <button>¡Oferta!</button>
        </section>

        <section class="tarjeta-producto">
            <h3>Otro Producto</h3>
            <p>Descripción breve de un producto estándar.</p>
            <button>Ver más</button>
        </section>

        <section class="tarjeta-producto">
            <h3>Último Producto</h3>
            <p>Descripción breve de un producto estándar.</p>
            <button>Ver más</button>
        </section>
    </main>

</body>

</html>

En resumen, Flexbox es la herramienta fundamental en CSS moderno para crear diseños complejos de una dimensión de forma sencilla, predecible y responsive. Es ideal para componentes de una aplicación, como barras de navegación, galerías de tarjetas o cualquier grupo de elementos que necesiten alinearse y distribuirse de forma dinámica.

Apartados de esta sección
Para containerPara itemsEjemplos

<< Nesting Para container >>