Maquetación con flexbox

¿Todavía usando tablas para maquetar? ¿Harto de usar floats? ¿Ni pajolera idea de cómo alinear verticalmente elementos? Pues con flexbox todo se hace más fácil.

Índice

Historia de la maquetación

La semántica en HTML ha ido cada vez a mejor con la aparición de nuevos elementos. Estos nuevos elementos mejoran la forma de trabajar con nuestro markup siendo más declarativa. Una buena semántica nos facilita el inferir cómo se va a representar gráficamente nuestra página dada una estructura.

Pero con la revolución de la web se veía cada vez más que no solamente se debía presentar la información, sino que además la presentación de dicha información tenía que ser visualmente agradable, con lo que se empezaron a reordenar los elementos con HTML y CSS para formar layouts nuevos y complejos. Todo esto se empezó a realizar con el elemento table. El problema es que ahora nuestro HTML dejaba de ser puramente semántico, puesto que el elemento table lo que ha de representar es una información tabulada.

Y de ahí pasamos a usar floats. Lo bonito de esta solución es que ya no quedaba nuestro HTML plagado de etiquetas td y tr y se pasaba a hacer uso de clases de CSS para indicar cómo debía quedar maquetada nuestra página.

Pero los floats tenían un problema: nunca se diseñaron para una labor como lo es la maquetación. Su cometido era alinear imágenes y texto. Nada más. Por lo que teníamos que hacer uso de hacks para conseguir gobernar nuestra web.

Viendo que la maquetación no era algo trivial muchos frameworks de CSS surgieron, entre ellos el más conocido: Bootstrap, pero también tenemos otros como Foundation o Pure.

Pasaron unos años hasta que el comité W3C decidió ponerse a trabajar en una solución que facilitase la labor del maquetado y por ello propuso la especificación de flexbox.

En resumidas cuentas flexbox es un mecanismo para maquetar de forma flexible, con facilidades para la justificación y alineación de elementos. Funciona mediante contenedores e hijos.

Introducción a flexbox

En flexbox tenemos un contenedor y uno o varios hijos. El contenedor es el elemento al que le vamos a indicar que se ponga en disposición flex con display: flex;. Esto hará que todos los elementos hijo inmediatos se coloquen a lo largo de un eje principal. Como siempre es todo mejor verlo con un ejemplo:

Nota: las unidades vh indican el alto del viewport (viewport height) y vw indica el ancho del viewport (viewport width). El viewport es la franja de espacio que ocupa lo que ve el usuario en la pantalla inicial. Más información aquí.

Y además, vamos a añadir este selector al principio de todos nuestros CSS:

¿Sabes lo que hace box-sizing: border-box;? Verás, con la propiedad box-sizing se puede redefinir de qué manera ha de calcular la altura y la anchura de los elementos de nuestra página. Es prácticamente obligatorio definir esta propiedad si queremos que nuestra maquetación sea predecible.

Lo que indica border-box es que tanto los paddings y bordes se apliquen en el interior de la caja. Aquí tienes más información.

Y esto produce lo siguiente:

Impresionante, ¿verdad? Pues no mucho si somos francos. La verdadera magia es cuando aplicamos propiedades al contenedor.

Contenedor

El contenedor recibe una serie de propiedades muy interesantes. Entre ellas tenemos justify-content, que nos permite hacer lo siguiente:

Esto ya pinta más interesante. Pero… ¿qué acabamos de hacer? Pues verás, cuando disponemos un elemento en modo flex lo que hacemos es colocar los elementos hijos a lo largo de un eje principal, y con justify-content podemos alinear los elementos del eje principal. En el caso anterior hemos puesto flex-end que lo alinea al final. El valor por defecto es flex-start. Veremos todas las demás propiedades más tarde.

En cuanto a los ejes; el eje por defecto es row. Y se puede modificar con flex-direction. Por ello vamos a probar a añadir un nuevo elemento al HTML:

Y como hemos mencionado antes, el eje principal puede ser modificado:

Si nos fijamos bien, vemos que los elementos se han dispuesto en filas. Y no solo eso, si no que vemos que los elementos se han alineado abajo del todo debido a justify-content: flex-end; dado que el eje principal ahora es de la Y.

Podemos también alinear en el eje secundario con align-items:

Esta vez hemos decidido alinear al centro con center. Y los demás valores que tanto justify-content como align-items pueden recibir son los siguientes:

Lo mejor para asimilar lo que hace cada uno de ellos es irlos probando vosotros mismos. Aun así os dejo aquí un mini resumen. El contenedor viene definido en todos los casos con flex-direction a row:

Aquí os dejo una guía completa de flexbox por si queréis indagar más.

Hijos

Otra parte importante de flexbox y que hasta ahora no hemos visto es su flexibilidad inherente. En los ejemplos anteriores hemos estado jugando con la justificación y alineación, pero si nos fijamos vemos que hemos definido los elementos con unos tamaño explícitos.

Una propiedad importante que reciben los hijos es flex. flex es una propiedad "acortada", es decir que por debajo son 3 propiedades distintas:

  • flex-grow: Define la habilidad de un hijo de ocupar espacio sobrante. Recibe un entero. Por defecto es 0.
  • flex-shrink: Define la habilidad de un hijo de encogerse. Recibe un entero. Por defecto es 0.
  • flex-basis: Esta propiedad especifica el tamaño base que ocupa un elemento hasta que éste se puede encoger o ensanchar. Su valor puede ser una unidad o auto (cuyo valor es el por defecto).

Aunque dispongamos de estas propiedades se recomienda usar el método acortado flex, dado que éste asigna valores inteligentemente.

La firma de flex es la siguiente:

El valor de flex por defecto es 0 1 auto.

Habiendo explicado el mecanismo de flex, ¿qué podemos hacer con él?

Y lo mejor de todo es que podemos alternar la propiedad flex de cada elemento para modificar su peso:

Responsividad avanzada

Vamos a pasar con responsividad. Si maquetamos con flexbox podemos llegar a hacer interacciones como la siguiente:

Esto se puede hacer con el siguiente HTML:

Y su CSS pertinente:

Hay una propiedad nueva: flex-wrap. Esta propiedad se aplica al contenedor y permite disponer a los hijos en varias lineas si surgiese la casuística de que no consiguiesen caber en una única línea.

Otra propiedad importante es flex: 1 400px;. Si os acordáis flex es un método acortado cuyo primer valor es el máximo que puede abarcar un elemento y la segunda unidad (ojo, en caso que incluyamos dos propiedades nada más; si no me crees revisa otra vez la firma de la propiedad de flex) especifica el flex-basis, que era la propiedad que indicaba el tamaño que debía abarcar hasta que cupiese otro elemento.

Y como en el contenedor hemos dicho que intentase meter todos los elementos posibles, lo que hará será, hasta que un nuevo elemento de 400px quepa en la fila superior, éste se repartirá el espacio sobrante entre todos los elementos de esa fila a partes iguales, ergo pasará lo que hemos visto en el vídeo.

Comparativa

Para aquellos que hayan visto mi tutorial de CSS grid se preguntarán cómo encaja flexbox en la maquetación si ya disponemos de una herramienta como grid. Pues bien, grid se usa para maquetar en dos dimensiones mientras que flexbox se usa comunmente para maquetar en una dimensión.

Por ejemplo, supongamos que tenemos una página. La estructura y el layout se haría con grid mientras que las celdas de la grilla bien podrían ser elementos de flexbox ya que podemos anidarlos sin ningún tipo de problema.

Conclusión

Un buen maquetador web ha de incluir en su cinturón de herramientas flexbox y grid si quiere crear diseños interesantes y complejos y no morir en el intento.

Y estas herramientas están aquí para quedarse. Solventan todos los problemas comunes (y no tan comunes) de la maquetación y dan al desarrollador la libertad de no tener que elegir una biblioteca de CSS para poder maquetar a gusto.