Layouts flexibles. Columnas del mismo alto. Vista independiente del HTML. Estas cosas no han sido fáciles de conseguir con CSS, hasta ahora. El diseño flexible de cajas, la nueva especificación de flexbox, hace que crear cualquiera de estos diseños sea mucho más fácil.
Este artículo te guiará a través de la especificación más reciente de flexbox y podrás usar el código del ejemplo para crear un diseño flexible y organizar cualquier elemento sin importar su orden en el código HTML.
Soporte para navegadores
Hay algunas malas noticias acerca de flexbox y el soporte con los navegadores. Aunque los navegadores más actuales soportan flexbox, han habido varias versiones de la especificación. El problema es que no todos los navegadores soportan la versión más reciente. A continuación se explica qué navegadores son compatibles con la especificación más reciente de flexbox.
- Opera – Es compatible con la especificación más reciente sin necesidad de prefijos de proveedor.
- Chrome – Es compatible con la especificación más reciente pero requiere el prefijo webkit.
- Safari – Es compatible con una versión anterior de la especificación con el prefijo webkit.
- Internet Explorer – Es compatible con una versión anterior de la especificación con el prefijo ms. Versiones anteriores a Internet Explorer 9 no son soportadas.
- Firefox – Es compatible con una versión anterior de la especificación con el prefijo mz, sin embargo una vez que llega la versión 20.0. Firefox tendrá soporte a la versión más reciente sin necesidad de prefijos.
Los dispositivos móviles con soporte para flexbox:
- iOS y Android – Tienen soporte para la versión anterior de la especificación utilizando el prefijo webkit.
- BlackBerry (10) – Es compatible con la especificación más reciente pero requiere el prefijo webkit.
- Opera mini – No tiene soporte con ninguna versión.
En otras palabras solo dos navegadores soportan la versión actual de la especificación.
Nota: En este artículo, tenga en cuenta que la especificación actual sólo funciona con versiones reciente de Chrome y Opera.
Para obtener más información visite el sitio de W3C.
Modelo flexible de cajas.
Las cajas flexibles es otro modelo de diseño. En flexbox has dos ejes, un eje principal y otro transversal. El eje principal es el eje primario y el eje que cruza es perpendicular al eje principal. Cada eje tiene una dimensión asociada y cada eje tiene un inicio y un punto final. Los elementos incluidos en el contenedor y el propio contenedor tienen un tamaño en función a su ancho y alto.
Cómo crear un Flexbox
La manera fácil de entender como funciona flexbox es verlo en acción. Para hacer esto, he configurado un demo con el siguiente código HTML. Las pantallas más amplias tendrán un diseño de tres columnas. Las pantallas pequeñas fluirán en una sola columna.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<p><div class="flex-container"><br> <div class="header"></p> <p>Header</p> <p></div><br> <div class="content"></p> <p>Main Content</p> <p></div><br> <div class="sidebar primary"></p> <p>Primary Sidebar</p> <p></div><br> <div class="sidebar secondary"></p> <p>Secondary Sidebar</p> <p></div><br> <div class="footer"></p> <p>Footer</p> <p></div><br> </div></p> |
En el ejemplo superior, tenemos una simple etiqueta div (flex-container). Las cinco etiquetas div internas ( header, content, sidebar, sidebar secundario y foooter ) serán flexibles.
No se muestra lorem ipsum en el container principal y etiquetas div del sidebar primario. También he establecido algunos estilos genéricos para colocar en cada etiqueta, un color de fondo y color de texto para que podamos distinguirlos fácilmente.
Para crear un flexbox, simplemente establece la propiedad display del contenedor en uno de los dos valores.
1 2 |
.flex-container {display: flex;} .flex-container {display: inline-flex;} |
El primero crea un lexbox de nivel bloque y el segundo un flexbox en línea. Para el ejemplo, crea un flexbox nivel bloque dentro del CSS, de la siguiente manera:
1 2 3 4 |
.flex-container { display: -webkit-flex; display: flex; } |
Se visualiza de la siguiente manera:
Con este código, hemos creado un flexbox, aunque no resulta tan emocionante. Todos los elementos dentro del flexbox son flex-items y fluyen uno tras otro, como si todos estuvieran flotando a la izquierda, eso si es interesante ya que no les indicamos que flotaran. Esto nos lleva a la propiedad flex-direction.
Nota: Chris Coyier tiene una excelente reseña sobre las antiguas y nuevas especificaciones de flexbox. Pero si deseas ampliar a más navegadores agrega a el código anterior estas líneas.
1 2 3 4 5 6 7 |
.flex-container { display: -webkit-box; /* OLD - iOS 6-, Safari 3.1-6 */ display: -moz-box; /* OLD - Firefox 19- (buggy but mostly works) */ display: -ms-flexbox; /* TWEENER - IE 10 */ display: -webkit-flex; /* NEW - Chrome */ display: flex; /* NEW, Spec - Opera 12.1, Firefox 20+ */ } |
Puedes leer la publicación de Chris, Using Flexbox: Mixing Old and new for the Best Browser Support, para más detalles.
Orden y Orientación
La razón por la que los flex-items, caen uno tras otro tiene que ver con la propiedad flex-direction. Esta propiedad establece la dirección del eje principal del flexbox. Hay cuatro posibles valores.
- row (the default)
- row-reverse
- column
- column-reverse
Puesto que no hemos fijado un valor, se obtiene la fila por defecto. Un valor row-reverse voltea todo horizontalmente. En este caso, la cabecera se inicia en el extremo derecho y, a continuación cada uno de los divs se coloca a la izquierda de la anterior, como si todos estuvieran flotando a la derecha.
Agregando flex-direction a la columna se establece el inicio del flexbox hasta arriba y cada div caerá uno sobre otro. Un valor de column-reverse inicia el flexbox en la parte inferior del contenedor.
Otra propiedad que se define junto con flex-direction es flex-wrap. La cual establece si el contenedor es un flexbox de una línea o múltiples líneas. Los posibles valores son los siguientes:
- nowrap
- wrap
- wrap-reverse
Puedes establecer estas propiedades con flex-flow. Al establecer flex-flow, se establece flex-direction seguida por flex-wrap. En el ejemplo, agrega la propiedad flex-flow de la siguiente manera:
1 2 3 4 |
.flex-container { -webkit-flex-flow: row wrap; flex-flow: row wrap; } |
Mencione que flexbox nos ayuda romper libremente el orden de los recursos. Si has estado trabajando con diseño sabes cuando esté es de una sola columna, las cajas están encima de otra en el código HTML. Se puede limitar dependiendo en función de lo que su diseño requiere, como que se expanda en columnas.
Flexbox elimina esta limitación con la propiedad order . Establecer la propiedad order en los elementos flexibles para definir cómo se visualizarán. La propiedad utiliza valores enteros. En el ejemplo no hay nada emocionante pero con el orden de los elementos flexibles (flex-items), no dudes en jugar. Coloca el siguiente código:
1 2 3 4 5 |
.header {-webkit-order: 1;} .content {-webkit-order: 2;} .primary {-webkit-order: 3;} .secondary {-webkit-order: 4;} .footer {-webkit-order: 5;} |
Para ver lo que se ha logrado hasta ahora, ve la captura de pantalla en mi sitio.
Hasta este punto probablemente te has convencido de que flexbox no tiene sentido, puesto que el ejemplo se ve exactamente igual con o sin ello. Vamos a cambiar eso para que veas cómo flexbox hace cambiar el diseño.
Con nuestro diseño por defecto todos los divs se muestran en una sola columna. Eso esta bien para un teléfono, pero qué pasa si quieres cambiar la visualización a una pequeña ventana que es un poco mas ancha? una vez que la pantalla es de al menos 48em de ancho, que pasa si ¿quieres que el contenido principal y el sidebar se muestre en dos columnas, una al lado de otra? Qué pasa si quieres cambiar el orden para que el sidebar vaya despues del contenido principal. Las siguientes modificaciones hacen precisamente eso:
1 2 3 4 5 6 7 8 9 10 |
@media screen and (min-width: 48em) { .content { width: 67%; -webkit-order: 3; } .primary { width: 33%; -webkit-order: 2; } } |
Observa lo fácil que era para cambiar el diseño. Basta con ajustar el ancho de cada div para que puedan encajar en una sola fila. Entonces, cambia el orden de modo que la barra lateral se muestre primero.
Para ver como se muestra el nuevo diseño, ve al sitio.
Los cambios fueron tan simples. ¿Te das cuenta de lo ocurrido sin tener que hacer nada? La altura del sidebar coincide con la altura de la columna del contenedor principal. No tenemos que hacer algo para que eso suceda. Añadir más párrafos al contenedor principal. Elimina alguno. Añadir suficientes elementos a la lista hace que la barra lateral se haga más larga. No importa; las columnas será siempre de la misma altura por el flexbox.
Esto no es malo, en absoluto. Unas pocas líneas de simple código para superar las limitaciones de tener que estructurar el HTML en un orden en particular, y columnas de misma altura de manera predeterminada.
Vamos a poner la barra lateral dentro de esto y expandir el layout a tres columnas. Mientras estamos en ello, vamos a pasar el sidebar primario hacia la derecha, después el sidebar secundario.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@media screen and (min-width: 60em) { .content { width: 50%; -webkit-order: 2; order: 2; } .primary { -webkit-order: 4; order: 4; } .secondary { -webkit-order: 3; order: 3; } .sidebar { width: 25%; } } |
Para ver como queda el nuevo diseño, ve mi sitio.
Nuevamente lo hemos hecho, es bastante fácil. He ajustado el ancho para que todo quede en un sola fila y cambie el orden de los flex-items. Ojala puedan ver lo fácil que es reorganizar un diseño con unas pocas líneas de código. Y una vez más, hay columnas de altura libre.
Hay unos cuantos conceptos más de Flexbox. Vamos ampliar el ejemplo hablando de ellos.
Cómo los flex items son flexibles
Uno de los beneficios de los flexboxes es que como el contenedor crece o se contrae, los elementos en el interior pueden también crecer o achicarse, manteniendo sus mismas proporciones. Mejor aún es que tienes que especificar el tamaño. Los elementos flexibles se ajustará a el tamaño para llenar la caja. Puedes utilizar las siguientes propiedades.
- flex-grow – especifica cuánto puede crecer un elemento en relación con otros elementos (valor entero)
- flex-shrink – especifica cuánto un elemento puede encoger en relación con otros elementos (valor entero)
- flex-basis – especifica el tamaño principal inicial del elemento Flex antes de que se distribuya el espacio libre (valor es width o auto)
- flex shorthand – none | [ <‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’> ]
Para ver los flexbox en acción, quita el texto dentro del div contenedor y reemplazalo con tres nuevos divs: Box1 Box2 y Box3. A continuación se muestra el código HTML con algunos lorem ipsum.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<p><div class="flex-container"><br> <div class="header"></p> <p>Header</p> <p></div><br> <div class="content flex-content"><br> <div class="box box1"></p> <p>Box 1</p> <p></div><br> <div class="box box2"></p> <p>Box 2</p> <p></div><br> <div class="box box3"></p> <p>Box 3</p> <p></div><br> </div><br> <div class="sidebar primary"></p> <p>Primary Sidebar</p> <p></div><br> <div class="sidebar secondary"></p> <p>Secondary Sidebar</p> <p></div><br> <div class="footer"></p> <p>Footer</p> <p></div><br> </div></p> |
Puse el div contenedor en su propio flexbox, por lo que ahora es un flexbox dentro de otro. Esta vez puse la columna a la misma dirección. Puesto que se debe establecer un altura para este contenedor, arbitrariamente lo configure a 30em.
1 2 3 4 5 6 7 |
.content { display: -webkit-flex; display: flex; -webkit-flex-flow: column wrap; flex-flow: column wrap; height: 30em; } |
Las tres cajas con un color de fondo y la propiedad flex-grow, quedan así:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
.box1 { background: #933; -webkit-flex-grow: 8; flex-grow: 8; } .box2 { background: #393; -webkit-flex-grow: 1; flex-grow: 1; } .box3 { background: #339; -webkit-flex-grow: 3; flex-grow: 3; } |
Para ver los resultados de este demo hasta este punto, visita mi sitio.
A continuación, cambiemos a un layout de dos columnas, cambiando el tamaño y el orden de las cajas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@media screen and (min-width: 48em) { .box1 { -webkit-flex-grow: 6; flex-grow: 6; -webkit-order: 1; order: 1; } .box2 { -webkit-order: 3; order: 3; } .box3 { -webkit-flex-grow: 1; flex-grow: 1; -webkit-order: 2; order: 2; } } |
Para ver el demo en este punto, visita mi sitio.
Una vez tenemos suficiente espacio para las tres columnas, cambiemos las cajas de nuevo, esta ve teniendo Box 1 en una columna mientras que las otras dos cajas comparten una columna debajo de esta. Primero, cambiemos la propiedad flex-flow para .content y así procesar la columna y entonces colocar a box1 con un width de 100%.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@media screen and (min-width: 60em) { .content { -webkit-flex-flow: row wrap; flex-flow: row wrap; } .box1{ width: 100%; } .box3 { -webkit-flex-grow: 2; flex-grow: 2; -webkit-order: 3; order: 3; } } |
Para ver el demo en este punto, visita mi sitio.
De nuevo, puedes hacer cambios importantes al layout con unas cuantas líneas de CSS. Puede que al inicio no parezca tan impresionante, pero en perspectiva, piensa acerca de lo que tendrías que hacer con JavaScript o JQuery para alcanzar los mismos cambios que con flexbox.
Alineando elementos Flex
Hasta ahora hemos tenido elementos Flex que llenan al contenedor sin la necesidad de especificar dimensiones. A veces los elementos en un contenedor Flex requieren de las dimensiones de alto y ancho. Por ejemplo, los elementos pueden ser imágenes de un tamaño fijo que deben mostrarse en una tabla.
Ajustemos el demo una vez más. He removido los valores de flex-grow en las tres cajas y en su lugar las modifique para que todas tuvieran el mismo alto y ancho:
1 2 3 4 |
.box { width: 25%; height: 5em; } |
Si haces que esto cambie veras que las cajas ya no llenan al contenedor y en su lugar inician desde arriba y se acomodan una debajo de otra. Esto es debido a la dirección del contenedor flex está establecida a columnas. Supongamos que nos gustaría que las cajas estuvieran distribuidas dentro del contenedor de otra forma. Hay muchas propiedades que puedes utilizar para hacerlo.
Puedes alinear elementos a lo largo del eje principal del contenedor con la propiedad jusfity-content, a la cual puedes asignar al contenedor flex con los siguientes valores:
flex-start – los posiciona al inicio
flex-end – los posiciona al final
center – los posiciona en el centro
space-between – los distribuye equitativamente en línea
space-around – los distribuye equitativamente en línea con la mitad de espacio al principio y al final
A lo largo del eje transversal tenemos dos propiedades similares.
align-items – conjunto en el contenedor, se convierte en la configuración predeterminada de todos los elementos Flex.
align-self – conjunto de elementos, sobrescribe align-items para ese elemento especifico.
Ambos usan las mismas flex-start, flex-end y center como jusfity-content y trabajan de la misma manera, excepto que actúan en dirección cruzada. Sin embargo, las propiedades space-around y space-between son reemplazadas con los siguientes valores, cada uno con su propio conjunto de reglas contextuales.
baseline – alinea el baseline de los elementos Flex para la línea cruzada.
btretch – extiende los elementos u poco para alinear los ítems Flex y baseline.
Ambas tienen algunas reglas detalladas de cómo trabajan, las cuales puedes encontrar aquí, aunque experimentar con ellas te ayudara a comprenderlas mejor.
He configurado un último demo para mostrar estas propiedades. Establecí un valor de space-between sobre jusfity-content y un valor de center para align-items. Agregue estos valores al div content.
1 2 3 4 5 6 |
.content { -webkit-justify-content: space-between; justify-content: space-between; -webkit-align-items: center; align-items: center; } |
He sobrescrito el valor align-items en dos de las cajas con la propiedad align-item.
1 2 3 4 5 6 7 8 |
.box1 { -webkit-align-self: baseline; align-self: baseline; } .box3 { -webkit-align-self: flex-end; align-self: flex-end; } |
Para ver los resultados de este último demo, visita mi sitio.
Mis valores son arbitrarios. Te invito a jugar con los diferentes valores y explorar lo que puedes hacer.
A donde ir desde aquí
Con ilusión te he mostrado que tan fácil se puede trabajar con flexbox e incluso que tan “flexible” es realmente. Después de jugar con flexbox una hora, probablemente estés mordiendo tus uñas esperando que todos los navegadores lo soporten para empezar a usarlo en producción.
De los cinco mejores navegadores de escritorio, la versión actual ya funciona en dos, con uno más que con el otro. En otro (Safari) probablemente obtendrá la última especificación dentro de poco, ya que funciona en webkit. Así como soporte para Internet Explorer, probablemente sueles lidiar con versiones viejas de este pero ahora ya hay polyfills de flexbox, como Flexie.
Desafortunadamente flexbox no está lo bastante listo todavía, pero se acerca cada vez más. Si deseas mezclar lo viejo y lo nuevo entre especificaciones puedes soportar muchos navegadores.
Ahora que la especificación se ha arreglado, creo que alcanzaremos el punto donde todos los navegadores actuales soportan la última especificación (posiblemente con prefijos para cada vendor). Solo necesitaremos considerar que tanto soporte de compatibilidad necesitaremos para Internet Explorer o si utilizaremos un polyfill.
En Activ puedes aprender a desarrollar sitios web responsivos con nuestro curso de HTML5 para móviles impartido por los mejores instructores de México
La versión original de este artículo está publicada en Adobe Devnet bajo licencia Creative Commons, fue traducido y adaptado en nuestro blog por Margarita García.
Trackbacks/Pingbacks