Flexbox es un conjunto de propiedades CSS que nos ayudan a crear layouts de nuestras páginas web de una manera más sencilla y fácil de entender sin necesidad de utilizar floats o elementos inline-block. Con pocas líneas de código podemos decidir el comportamiento de nuestros elementos (columnas, filas, dirección, alineación, tamaño, orden, etc). A continuación estudiaremos las principales propiedades de Flexbox.

Contenedores Flexbox

Para empezar a trabajar con Flexbox necesitamos crear un contenedor con la propiedad display: flex.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" href="styles.css" />
</head>
<body>
  <div class="container">
    <div class="container__item bg--blue">Uno</div>
    <div class="container__item bg--red">Dos</div>
    <div class="container__item bg--purple">Tres</div>
    <div class="container__item bg--yellow">Cuatro</div>
  </div>
</body>
</html>
.container {
  background: #ecf0f1;
  display: flex;
  height: 400px;
  margin-left: auto;
  margin-right: auto;
  width: 800px;
}

.bg--blue {
  background: #3498db;
}

.bg--red {
  background: #c0392b;
}

.bg--purple {
  background: #9b59b6;
}

.bg--yellow {
  background: #f1c40f;
}

Tradicionalmente sabemos que los elementos div de nuestra página tienen un display block por lo cual se acomodan uno debajo del otro. Pero cuando nuestro contenedor tiene la propiedad display: flex sus hijos directos obtienen propiedades de Flexbox y el primer comportamiento que notarás es que estos se convierten en columnas, que ocupan el ancho de acuerdo a su contenido dentro de ellos y que además ocupan todo el alto disponible de su contenedor.

Flex container

Ancho de columnas

Sabemos que los hijos directos de un contenedor con display: flex por defecto se acomodarán en forma de columnas uno después de otro y que su ancho queda definido por su contenido dentro de ellos. Ahora veremos como establecer el ancho de esos elementos con otras propiedades de Flexbox.

flex-basis

Con la propiedad flex-basis podemos establecer el ancho inicial de los elementos de un contenedor flex.

.container__item {
  flex-basis: 150px;
}

Nuestro layout se ve algo así:

Flex basis

flex-grow

Ahora veremos como hacer crecer el ancho de nuestras columnas con la propiedad flex-grow para que puedan llenar todo el ancho de su contenedor:

.container__item {
  flex-basis: 150px;
  flex-grow: 1;
}

Flex grow

Lo que hizo flex-grow: 1; es hacer crecer todos los elementos de la misma manera para que puedan llenar el espacio de su contenedor.

Veamos que pasa cuando queremos hacer crecer uno de los elementos 2 veces para entender como funciona flex-grow.

.container__item:nth-child(2) {
  flex-grow: 2;
}

Flex grow

Hacer crecer un elemento 2 veces con flex-grow no quiere decir que este elemento va tener el doble de tamaño que sus hermanos. Lo que quiere decir es que va tener 2 veces el crecimiento que tuvieron sus hermanos en relación al ancho inicial que definimos anteriormente con flex-basis.

Los elementos que hicimos crecer 1 vez con flex-grow: 1; tuvieron un crecimiento de +40px cuando el ancho inicial con flex-basis fue de 150px, dando un total de 190px.

grow 1

El elemento que hicimos crecer 2 veces con flex-grow: 2; entonces creció dos veces más que sus hermanos +80px, dando un total de 230px.

grow 2

flex-shrink

Con esta propiedad podemos encoger el ancho de nuestras columnas, justo lo opuesto de flex-grow aunque funcionan de manera similar:

.container__item {
  flex-basis: 400px;
  flex-shrink: 1;
}

.container__item:nth-child(2) {
  flex-shrink: 2;
}

Flex grow

Todos los elementos tienen un ancho inicial de 400px establecido con flex-basis. Los elementos que se encogieron 1 vez con flex-shrink: 1; redujeron su tamaño -160px, dando un total de 240px.

shrink 1

El segundo elemento que hicimos encoger su ancho 2 veces más que sus hermanos entonces se redujo -320px, dando un ancho total de 80px.

shrink 2

flex

La propiedad flex es un shorthand para establecer los siguientes valores.

  • flex-grow
  • flex-shrink
  • flex-basis
.container__item {
  flex: 1 1 400px;
}

.container__item:nth-child(2) {
  flex: 1 2 400px;
}

Flex grow

Si queremos podemos pasar únicamente el primer valor, y veamos que es lo que pasa:

.container__item {
  flex: 1;
}

.container__item:nth-child(2) {
  flex: 2;
}

Flex grow

Como podemos observar pasando solo el primer valor podemos hacer fácilmente que uno de los elementos sea del doble de ancho que sus hermanos.

Filas o Columnas

Anteriormente vimos que por defecto los elementos dentro de nuestro contenedor flex se acomodaban de manera horizontal uno después del otro. Pero podemos decidir ese comportamiento con la propiedad flex-direction.

flex-direction

Esta propiedad la escribiremos en nuestro contenedor flex. El valor por defecto que este tiene es flex-direction: row;.

.container {
  background: #ecf0f1;
  display: flex;
  flex-direction: row;
  height: 400px;
  margin-left: auto;
  margin-right: auto;
  width: 800px;
}

Flex grow

Podemos hacer que los elementos se acomoden de manera vertical uno debajo de otro con flex-direction: column;.

Flex column

También podemos hacer que los elementos se acomoden al revés con los siguientes valores:

  • flex-direction: row-reverse;
  • flex-direction: column-reverse;

column reverse

Orden de los elementos

Con Flexbox podemos establecer el orden de los elementos de un contenedor flex. Para ello utilizamos la propiedad order en cada uno de los elementos.

order

Establece el orden del elemento dentro de el contenedor flex.

.container {
  background: #ecf0f1;
  display: flex;
  flex-direction: row;
  height: 400px;
  margin-left: auto;
  margin-right: auto;
  width: 800px;
}

.container__item {
  flex: 1;
}

.container__item:nth-child(2) {
  order: 1;
}

.container__item:first-child {
  order: 2;
}

.container__item:nth-child(3) {
  order: 4;
}

.container__item:last-child {
  order: 3;
}

Order

Ajuste de elementos

Para ver otras propiedades de Flexbox vamos a actualizar un poco el contenido de nuestro documento HTML.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <link rel="stylesheet" href="styles.css" />
</head>
<body>
  <div class="container">
    <div class="container__item bg--blue">
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.</p>
    </div>
    <div class="container__item bg--red">
      <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
    </div>
    <div class="container__item bg--purple">
      <p>Donec nec justo eget felis facilisis fermentum. Aliquam porttitor mauris sit amet orci. Aenean dignissim pellentesque felis.</p>
    </div>
    <div class="container__item bg--yellow">
      <p>Integer vitae libero ac risus egestas placerat.</p>
    </div>
  </div>
</body>
</html>

Asignamos un ancho máximo a nuestro contenedor de 800px y eliminamos el alto.

.container {
  background: #ecf0f1;
  display: flex;
  flex-direction: row;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
}

.container__item {
  flex: 1;
}

Entonces si redimensionamos nuestro navegador veremos que tenemos elementos que se ajustan de manera automática al ancho que llegue a tener su contenedor.

Fluid

Pero nosotros queremos establecer un ancho mínimo pues no queremos que todo quede tan apretado.

.container__item {
  flex: 1;
  min-width: 150px;
}

Overflow

Entonces para evitar que se salgan los elementos del contenedor usaremos la propiedad flex-wrap.

flex-wrap

Con esta propiedad podemos hacer que los elementos del contenedor flex se ajusten de diferentes maneras. Por defecto nowrap.

  • nowrap
  • wrap
  • wrap-reverse
.container {
  background: #ecf0f1;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
}

Wrap

Con flex-wrap: wrap; los elementos que ya no caben se acomodan en la siguiente línea (líneas flex).

flex-flow

Esta propiedad es un shorthand para establecer las siguientes propiedades de una sola vez:

  • flext-direction
  • flex-wrap
.container {
  background: #ecf0f1;
  display: flex;
  flex-flow: row wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
}

Main Axis y Cross Axis

En Flexbox existen dos ejes en los cuales los elementos flex son colocados:

Main Axis

Es el eje principal donde los elementos flex se van posicionado uno después de otro.

Cross Axis

Es el eje perpendicular al Main Axis

Veamos siguiente ejemplo para describir los ejes:

.container {
  background: #ecf0f1;
  display: flex;
  flex-flow: row wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
  min-height: 494px;
}

.container__item {
  flex-basis: 150px;
  height: 200px;
}

Axis

Una vez que conocemos estos ejes vamos a ver como podemos alinear nuestros elementos en base a estos.

Alineación en Cross Axis

Primero hagamos algunos ajustes para establecer un ancho inicial de nuestros elementos de 400px.

.container__item {
  flex-basis: 400px;
  flex-grow: 1;
  height: 200px;
}

Cross Axis

Al hacer estos nuestros elementos se van desbordando hacia la siguiente línea sobre el Cross Axis.

align-content

Esta propiedad nos ayuda a alinear nuestros elementos sobre el Cross Axis y puede recibir multiples valores.

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • space-evenly
  • stretch

Ejemplo con align-content: flex-start;

.container {
  background: #ecf0f1;
  display: flex;
  flex-flow: row wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
  min-height: 494px;
  align-content: flex-start;
}

Align Content Start

Ejemplo con align-content: center;

Align Content Center

Nota: Únicamente funciona cuando hay elementos que se desbordan en otra línea sobre el Cross Axis y solo sobre esas líneas.

align-items

Esta propiedad alinea cada uno de los elementos flex sobre el Cross Axis, por defecto tiene un valor de stretch que hace que estos ocupen todo el alto de su contenedor, pero puede recibir los siguientes valores.

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch

Ejemplo con align-items: center;

.container {
  background: #ecf0f1;
  display: flex;
  flex-flow: row wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
  min-height: 494px;
  align-items: center;
}

.container__item {
  flex-basis: 150px;
  flex-grow: 1;
}

Align Items Center

align-self

También es posible alinear cada uno de los elementos de manera individual. La propiedad align-self es aplicada a los elementos flex y puede recibir los mismos valores que la propiedad align-items.

Ejemplo con align-self: flex-start;

.container__item:last-child {
  align-self: flex-start;
}

Align Self

Alineación en Main Axis

Ahora veamos como podemos alinear nuestros elementos sobre el eje principal.

justify-content

Esta es la propiedad que nos permite alinear nuestros elementos en el Main Axis y puede recibir los siguientes valores.

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around

Ejemplo con justify-content: space-between;

.container {
  background: #ecf0f1;
  display: flex;
  flex-flow: row wrap;
  margin-left: auto;
  margin-right: auto;
  max-width: 800px;
  min-height: 494px;
  justify-content: space-between;
}

.container__item {
  flex-basis: 150px;
}

Justify Content Space Betweeen

Prefijos propietarios

Flexbox no funciona por defecto en todos los navegadores, debemos agregar prefijos propietarios.

http://caniuse.com/#feat=flexbox

#flex-container > .flex-item {
  -webkit-flex: auto;
  flex: auto;
}

Ejemplo

http://codepen.io/montalvomiguelo/full/qReBgE/