Guía de Introducción a Flex

Modelo de cajas flexibles


Flex (también llamado flexbox) es un sistema de elementos flexibles que llega con la idea de olvidar mecanismos anticuados y acostumbrarnos a una mecánica más potente, limpia y personalizable, en la que los elementos HTML se adaptan y colocan automáticamente y es mucho más fácil personalizar los diseños de una página web.

Flex CSS

Flex está especialmente diseñado para los siguientes escenarios:

  • Crear estructuras simples de una sóla dimensión (no está limitado sólo a eso).
  • Estructuras flexibles que no queremos que sean de un tamaño específico (adaptables).
  • Crear diseños complejos enfocándote específicamente sólo en la estructura "actual".

Conceptos

Antes de utilizar flex lo primero que debemos hacer es conocer algunos de los conceptos básicos de este nuevo esquema, que son los siguientes:

Flex CSS: ¿Cómo funciona?

  • Contenedor: Es el elemento padre que tendrá en su interior cada uno de los ítems flexibles. Observa que al contrario que muchas otras estructuras CSS, por norma general, en Flex establecemos las propiedades al elemento padre.

    • Eje principal: Los contenedores flexibles tendrán una orientación principal específica. Por defecto, el eje principal del contenedor flex es en horizontal (en fila).

    • Eje secundario: De la misma forma, los contenedores flexibles tendrán una orientación secundaria, perpendicular a la principal. Si la principal es en horizontal, la secundaria será en vertical (y viceversa).

  • Ítem: Cada uno de los hijos que tendrá el contenedor en su interior.

Modalidades de flex

Una vez tenemos claro esto, imaginemos el siguiente escenario:

<div class="container"> <!-- Flex container -->
  <div class="item item-1">1</div> <!-- Flex items -->
  <div class="item item-2">2</div>
  <div class="item item-3">3</div>
</div>

Para activar el modo flex, utilizaremos sobre el elemento contenedor la propiedad display, y especificaremos el valor flex o inline-flex (dependiendo de como queramos que se comporte el contenedor):

Tipo de elementoDescripción
inline-flexContenedor en línea, similar a inline-block (ocupa solo el contenido).
flexContenedor en bloque, similar a block (ocupa todo el ancho del padre).

Por defecto, y sólo con esto, observaremos que los elementos se disponen todos sobre una misma línea. Esto ocurre porque estamos utilizando el modo flex y estaremos trabajando con ítems flexibles básicos, garantizando que no se desbordarán ni mostrarán los problemas que, por ejemplo, tienen los porcentajes sobre elementos que no utilizan flex.

1
2
3

Dirección

Existen dos propiedades principales para manipular la dirección y comportamiento de los ítems a lo largo del eje principal del contenedor. Son las que veremos a continuación:

PropiedadValorSignificado
flex-directionrow | row-reverse | column | column-reverseCambia la orientación del eje principal.

Mediante la propiedad flex-direction podemos modificar la dirección del eje principal del contenedor para que se oriente en horizontal (valor por defecto) o en vertical. Además, también podemos incluir el sufijo -reverse para indicar que coloque los ítems en orden inverso.

ValorDescripción
rowEje principal en dirección horizontal.
row-reverseEje principal en dirección horizontal invertida.
columnEje principal en dirección vertical.
column-reverseEje principal en dirección vertical invertida.

Esto nos permite tener un control muy alto sobre el orden de los elementos en una página. Veamos la aplicación de estas propiedades sobre el ejemplo anterior, para modificar el flujo del eje principal del contenedor:

.container {
  display: flex;
  flex-direction: column;
  background: darkgrey;
}

.item {
  background: indigo;
}

A continuación podemos ver un ejemplo interactivo:

1
2
3

Desborde multilinea (wrap)

En general, flex se suele utilizar para estructuras de una sola dimensión, es decir, contenedores que sólo van en una dirección. Sin embargo, existe una propiedad denominada flex-wrap con la que podemos especificar un comportamiento especial de nuestro contenedor padre.

Si un elemento no cabe dentro de nuestro contenedor flex, por defecto, los elementos se harán más pequeños (son flexibles) para ajustarse al contenedor. Este es el comportamiento por defecto de un contenedor flex. Sin embargo, con la propiedad flex-wrap podemos cambiar este comportamiento y permitir que nuestro contenedor flex se desborde, convirtiéndose en un contenedor flex multilínea.

PropiedadValorSignificado
flex-wrapnowrap | wrap | wrap-reverseEvita o permite el desbordamiento (multilinea).

Los valores que puede tomar esta propiedad, son las siguientes:

ValorDescripción
nowrapLos ítems se ajustan para ocupar el tamaño del contenedor (no permite desbordamiento en múltiples líneas).
wrapEstablece los ítems en modo multilínea (permite que se desborde el contenedor).
wrap-reverseEstablece los ítems en modo multilínea, pero en dirección inversa.

Teniendo en cuenta estos valores de la propiedad flex-wrap, podemos conseguir cosas como la siguiente:

.container {
  display: flex;
  flex-wrap: wrap;
  background: darkgrey;
}

.item {
  background: indigo;
}

Imagina ahora, que en nuestro contenedor flex tenemos muchos elementos, por ejemplo, 15 elementos hijos que no caben en el ancho del contenedor padre. Por defecto y siempre que pueda, flex hará más pequeños los elementos hijos para que quepan.

Sin embargo, si especificamos wrap en la propiedad flex-wrap, lo que permitimos es que el contenedor pueda tener múltiples lineas, mostrando los ítems que quepan en la primera linea, y el resto reubicándose en las siguientes líneas, sin ajustar su tamaño. El valor wrap-reverse haría exactamente lo mismo, pero con el orden inverso.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

La propiedad de atajo flex-flow

Recuerda que existe una propiedad de atajo (short-hand) llamada flex-flow, con la que podemos resumir los valores de las propiedades flex-direction y flex-wrap, especificándolas en una sola propiedad y ahorrándonos utilizar las propiedades concretas:

.container {
  /* flex-flow: <flex-direction> <flex-wrap>; */
  flex-flow: row wrap;
}

Huecos (gaps)

Existen dos propiedades muy interesantes llamadas: row-gap y column-gap. Dichas propiedades, permiten establecer el tamaño de los «huecos» entre ítems de un contenedor flex. Esto evita la necesidad de estar utilizando padding o margin en los elementos hijos, que suele traer muchas complicaciones.

PropiedadValorDescripción
row-gapnormal | Espacio entre filas (sólo funciona con flex-direction: column)
column-gapnormal | Espacio entre columnas (sólo funciona con flex-direction: row)

Como flex es un sistema que trabaja en una sola dimensión, sólo una de las dos propiedades tendrá efecto:

  • Si flex-direction: column, podrás utilizar row-gap.
  • Si flex-direction: row, podrás utilizar column-gap.

Eso sí, es posible usar ambas si tenemos la propiedad flex-wrap definida a wrap y, por lo tanto, disponemos de multicolumnas flexbox, ya que en este caso si podemos separar elementos por filas y por columnas.

1
2
3

Ten en cuenta que los huecos sólo se aplican entre elementos, y no entre un elemento hijo y su contenedor padre.

La propiedad de atajo gap

En Flex CSS existe una propiedad de atajo para los huecos, denominada gap. Con esta propiedad podemos indicar de una sola vez valores para row-gap y column-gap. Escribimos menos y es más cómodo:

PropiedadValorDescripción
gap0 | Aplica el tamaño del hueco en ambos ejes.
gap0 0 | Aplica los tamaños para el hueco del eje X y el eje Y.

Como se puede ver, por defecto, el tamaño de los huecos es de 0, sin embargo, podemos utilizar tanto las propiedades individuales como la propiedad de atajo gap para modificar estos tamaños.

A continuación, podemos ver un ejemplo de su utilización en este fragmento de código:

.container {
  /* 2 parámetros: <row> <column> */
  gap: 4px 8px;
  /* Equivalente a */
  row-gap: 4px;
  column-gap: 8px;

  /* 1 parámetro: usa el mismo para ambos */
  gap: 4px;
  /* Equivalente a */
  row-gap: 4px;
  column-gap: 4px;
}

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev