Sergio Xalambrí
December 14, 2013

# El módulo Flexbox de CSS3

Flexbox es un módulo de CSS3 que permite crear layouts flexibles de una forma más eficiente controlando la alineación de las cajas, el ancho y el alto para ocupar el espacio disponible. Un ejemplo simple es que con flexbox puedes hacer que todas las columnas de un sitio tengan el mismo alto y hasta hacer el responsive design mucho más fácil.

## Características principales de Flexbox

Algunas de las propiedades de Flexbox se deben aplicar al elemento padre (llamado flex container) y otros deben ser aplicados a los elementos hijos (llamados flex items).

En un layout flex tenés propiedades main y propiedades cross, entre las main están el main size, main axis, main-start y main-end y entre las cross están cross-size, cross-axis, cross-start y cross-end.

- main size: el ancho o alto del elemento padre creado en base al de los elementos hijos.
- main-start | main-end: el punto donde empieza y termina el flex content.
- main axis: es el eje principal del flex container en base a los flex items, este puede ser tanto horizontal como vertical dependiendo de la propiedad justify-content.
- cross size: es el ancho y alto de los flex items.
- cross-start | cross-end: el punto donde empiezan y terminan los flex item. Este es para todo el grupo no individual, esto es por si el flex content tiene un padding por ejemplo.
- cross axis: es el eje perpendicular al main axis y por tanto depende de este.

## Propiedades de Flexbox

Ahora sí, veamos las propiedades que forman Flexbox.

### display: flex | inline-flex (se aplica al flex container)

Esta es la propiedad principal, define cuál elemento es el flex container y si éste es block o inline, al estar definido habilita el contexto flex a todos sus elementos hijos.

- display: otros valores | flex | inline-flex;

> La propiedad column de CSS no afecta a un flex container. float, clear y vertical-aling tampoco afecta a un flex container.

### flex-direction (se aplica al flex container)

Establece el main axis definiendo por tanto la dirección en la que los flex item se ubican.

- flex-direction: row | row-reverse | column | column-reverse
- row (default): los elementos se ubican uno al lado de otro siguiendo el mismo orden que tienen en el HTML.
- row-reverse: los elementos se ubican en el orden contrario al del HTML.
- column: los elemento se ubican uno debajo de otro en el mismo orden que tienen en el HTML.
- column-reverse: similar a row-reverse.

### flex-wrap (se aplica al flex container)

Define si el flex container es multilinea o de una sola línea y la dirección del cross axis.

- flex-wrap: nowrap | wrap | wrap-reverse;
- nowrap (default): de una línea.
- wrap: multilínea (causa el mismo efecto que poner column).
- wrap-reverse: multilínea invertido (como column-reverse).

### flex-flow (se aplica al flex container)

Esta es una forma abreviada de flex-direction y flex-wrap para definir el main axis y cross axis juntos. El valor por defecto es “row nowrap”.

- flex-flow: flex-direction flex-wrap;

### justify-content (se aplica al flex container)

Define el alineamiento a lo largo del main axis. Ayuda a distribuir los restos de espacio libre adicional cuando todos los flex items en una línea alcanzaron su tamaño máximo.

- justify-content: flex-start | flex-end | center | space-between | space-around;
- flex-start (default): los flex items están ubicado en el punto main-start.
- flex-end: los flex item están ubicado en el punto main-end.
- center: los flex item están centrados en el main axis.
- space-between: los flex item estan distribuidos de forma que el primero esté en el main-start y el último en el main-end.
- space-around: los flex item están distribuidos con espacios iguales entre ellos.

### align-items (se aplica al flex-container)

Define el alineamiento a lo largo del cross-axis, piensa en justifiy-content en versión para el cross axis (perpendicular al main axis).

- aling-items: flex-start | flex-end | center | baseline | stretch;
- flex-start: similar al de justify-content pero sobre el cross-start.
- flex-end: como el de justify-content pero sobre el cross-end.
- center: los alinea de forma centrado según el cross axis.
- baseline: los flex item están alineados de forma que sus baseline se alinean.
- stratch (default): los flex item llenan el contenedor (se respeta siempre cualquier min/max aplicado).

### align-content (se aplica al flex container)

Este funciona exactamente igual que justify-content, pero sobre el cross axis permitiéndote definir qué hacer con el espacio que sobra. Esta propiedad no surte efecto cuando flexbox es de solo una línea.

- align-content: flex-start | flex-end | center | space-between | space-around | stretch;
- flex-start: las líneas se ubican al principio del contenedor.
- flex-end: las líneas se ubican al final del contenedor.
- center: las lineas se centran en el contenedor.
- space-between: las primera queda al principio del contenedor, la última al final, el resto separadas por la misma cantidad de espacio.
- space-around: las líneas quedan todas separadas por la misma cantidad de espacio.
- stretch: las líneas ocupan el tamaño restante.

### order (se aplica a los flex item)

Por defecto los flex item se ubican según el orden que tienen en el HTML. La propiedad order te permite tomar el controlar del orden en que estos aparecen en el contenedor.

- order:
  `<entero>`;

### flex-grow (se aplica a los flex item)

Define la capacidad de los flex item de crecer si es necesario, esto dicta la cantidad de espacio que pueden tomar dentro del contenedor. Si todos los item tienen flex-grow en 1, todos los flex item van a tener el mismo tamaño dentro del flex container. Si uno de los flex item tiene un valor de 2, este ocupará el doble de tamaño que los demás.

- flex-grow: `<número>` (default 0);

> Los número negativos no son válidos.

### flex-shrink (se aplica a los flex item)

Define la capacidad de los flex item de encogerse si es necesario.

- flex-shrink: `<número>` (default 1);

> Los número negativos no son válidos.

### flex-basis (se aplica a los flex item)

Define el tamaño por defecto de los elementos antes de que el espacio restante se distribuya.

- flex-basis: `<tamaño>` | auto (default auto);

### flex (se aplica a los flex item)

Es la forma abreviada de flex-grow, flex-shrink y flex-basis. El segundo y tercer parámetro (flex-shrink y flex-basis) son opcionales. Por defecto es “0 1 auto”.

- flex: none | flex-grow flex-shrink flex-basis

### align-self (se aplica a los flex item)

Esta propiedad permite sobreescribir para un flex item en particular el alineamiento dado por align-items.

- aling-selft: auto | flex-start | flex-end | center | baseline | stretch;

## Ejemplo de un layout con Flexbox

Acá les dejo un código para que vean cómo funciona usando (casi) todas las propiedades de flex:

    <!doctype html>
    <html lang="es">
    <head>
       <meta charset="utf-8" />
       <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
       <meta author="Sergio Daniel Xalambrí" />
       <meta name="description" content="Layout estilo blog usando Flex" />
       <title>Flex Blog Layout</title>
       <meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0" />
       <link rel="stylesheet" href="normalize.css" type="text/css" media="screen" />
       <link rel="stylesheet" href="main.css" type="text/css" media="screen" />
    </head>
    <body>
       <header>
          <h1>
             Flex Blog Layout
          </h1>
       </header>

       <div id="wrapper">

          <aside>
             <div>
                <h2>Widget 1</h2>
             </div>
             <div>
                <h2>Widget 2</h2>
             </div>
             <div>
                <h2>Widget 3</h2>
             </div>
             <div>
                <h2>Widget 4</h2>
             </div>
             <div>
                <h2>Widget 5</h2>
             </div>
          </aside>

          <section>
             <article>
                <h2>Post 1</h2>
                <p>
                   Normally, both your asses would be dead as fucking fried chicken, but you happen to pull this shit while I'm in a transitional period so I don't wanna kill you, I wanna help you. But I can't give you this case, it don't belong to me. Besides, I've already been through too much shit this morning over this case to hand it over to your dumb ass.
                </p>
                <p>
                   Do you see any Teletubbies in here? Do you see a slender plastic tag clipped to my shirt with my name printed on it? Do you see a little Asian child with a blank expression on his face sitting outside on a mechanical helicopter that shakes when you put quarters in it? No? Well, that's what you see at a toy store. And you must think you're in a toy store, because you're here shopping for an infant named Jeb.
                </p>
                <p>
                   Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. Some pilots get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing.
                </p>
             </article>
             <article>
                <h2>Post 2</h2>
                <p>
                   You think water moves fast? You should see ice. It moves like it has a mind. Like it knows it killed the world once and got a taste for murder. After the avalanche, it took us a week to climb out. Now, I don't know exactly when we turned on each other, but I know that seven of us survived the slide... and only five made it out. Now we took an oath, that I'm breaking now. We said we'd say it was the snow that killed the other two, but it wasn't. Nature is lethal but it doesn't hold a candle to man.
                </p>

                <p>
                   Look, just because I don't be givin' no man a foot massage don't make it right for Marsellus to throw Antwone into a glass motherfuckin' house, fuckin' up the way the nigger talks. Motherfucker do that shit to me, he better paralyze my ass, 'cause I'll kill the motherfucker, know what I'm sayin'?
                </p>

                <p>
                   My money's in that office, right? If she start giving me some bullshit about it ain't there, and we got to go someplace else and get it, I'm gonna shoot you in the head then and there. Then I'm gonna shoot that bitch in the kneecaps, find out where my goddamn money is. She gonna tell me too. Hey, look at me when I'm talking to you, motherfucker. You listen: we go in there, and that nigga Winston or anybody else is in there, you the first motherfucker to get shot. You understand?
                </p>
             </article>
          </section>

       </div>

       <footer>
          <p>Desarrollado por <a href="//twitter.com/sergiodxa">@sergiodxa</a></p>
       </footer>
    </body>
    </html>

    flexbox()
       display -webkit-box
       display -moz-box
       display -ms-flexbox
       display -webkit-flex
       display flex
    order()
       -webkit-box-ordinal-group arguments
       -moz-box-ordinal-group arguments
       -ms-flex-order arguments
       -webkit-order arguments
       order arguments

    footer
    header
       background #b2b2b2
       overflow hidden
       padding 10px
       text-align center

    footer
       line-height 25px

    h1
       margin 0

    header
       line-height 75px

    #wrapper
       display -webkit-box
       display -moz-box
       display -ms-flexbox
       display -webkit-flex
       display flex
       flex-flow row

       aside
       section
          display -webkit-box
          display -moz-box
          display -ms-flexbox
          display -webkit-flex
          display flex
          flex-grow 1
          article
          div
             color #fdfdfd
             background #666666
             flex-grow 1
             margin 10px
             padding 5px
             h2
                margin 0
             p
                margin 5px 0

       aside
          flex-flow column
          background #cccccc
          width 25%

       section
          flex-flow row
          width 75%

    @media screen and (max-width: 1000px) and (min-width: 640px)
       #wrapper
          section
             flex-flow column

    @media screen and (max-width: 640px)
       #wrapper
          flex-flow column
          aside
             -webkit-box-ordinal-group 2
             -moz-box-ordinal-group 2
             -ms-flex-order 2
             -webkit-order 2
             order 2
             width auto
          section
             flex-flow column
             -webkit-box-ordinal-group 1
             -moz-box-ordinal-group 1
             -ms-flex-order 1
             -webkit-order 1
             order 1
             width auto

> Repositorio en Github

> Demo

## Soporte de navegadores

Vamos a la parte más importante: qué navegadores lo soportan para saber si se puede usar:

- Chrome: hasta la versión 20 usando display: box y desde la versión 21 usando display: flex.
- Safari: desde las 3.1 usando display: box.
- Firefox: de la 2 a la 21 usando display: box y desde la 22 usando display: flex.
- Opera: desde la 12.1 usando display: flex.
- IE: desde la 10 usando display: flexbox.
- Android browser: desde la 2.1 usando display: box.
- Safari mobile: desde la 3.2 usando display: box.
- Blackberry browser: desde la 10 usando display: flex.

Para más información acá esta el línk a Can I Use:

> https://caniuse.com/#feat=flexbox

Y para terminar unos mixins hechos en Stylus para ayudarte a que funcione sin problemas.

    flexbox()
       display -webkit-box
       display -moz-box
       display -ms-flexbox
       display -webkit-flex
       display flex
    flex()
       -webkit-box-flex arguments
       -moz-box-flex arguments
       -ms-flex arguments
       flex arguments
    order()
       -webkit-box-ordinal-group arguments
       -moz-box-ordinal-group arguments
       -ms-flex-order arguments
       -webkit-order arguments
       order arguments

Más información: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes