soy Kseso y esto EsCSS

Flexible Box Model Layout o el modelo de caja flexible (flexbox) en Css3 a fondo.

Flexible Box Model Layout o el modelo de caja flexible (flexbox) en Css3 a fondo.

·Por Kseso ✎ 9

A modo de introducción

Posiblemente la mayor revolución que ha traído CSS3 ha sido la que menos atención haya recibido. Mucho se ha escrito sobre "cosillas menores" como las sombras, las esquinas redondeadas y demás propiedades "de adorno". Que están muy bien, pero no dejan de ser meras florituras.
El modelo flexible de caja (Flexible Box Model Layout o flexbox) supone la mayor revolución que el consorcio haya realizado, modifica radicalmente uno de los pilares de css que se ha mantenido prácticamente inalterado hasta ahora.
Ese pilar no es otro que el modelo de caja (box model). La estructura del documento y cómo se relacionan unas cajas con otras.

Este nuevo modelo de caja y las herramientas que incorpora significa terminar con la dictadura que imponía hasta la fecha el orden de aparición de los diferentes tags en el documento origen.
A la vez muchas de las carencias de Css2.1 en el control de las cajas quedan superadas al utilizar el flexbox. Y otras muchas que requerían de ingenio y realizaciones complejas dejan de serlo.

AVISO de actualización:
Para las propiedades, valores y funciones según la nueva sintaxis ver el artículo:El nuevo flexbox.
Las ideas, conceptos y la terminología empleados en este artículo siguen siendo válidos casi en su totalidad.

Lo que dice el draf sobre el flexbox

CSS 2.1 define cuatro modos de esquemas de algoritmos que determinan el tamaño y la posición de las cajas en base a sus relaciones con sus hermanos y sus ancestros: el diseño de bloques (display:block), diseño en línea (display:inline), diseñado para los textos; diseño en tablas (display:table), diseñados para presentación de la información en un formato tabular, y el diseño posicionado (position), diseñado para un posicionamiento muy explícito, sin mucha consideración con los demás elementos en el documento.
Este módulo presenta un forma nueva de diseñar el layout, el diseño FlexBox, que está pensado para realizar aplicaciones y páginas web más complejas de forma más simple.

El contenido de un FlexBox (items) se puede colocar en cualquier dirección (izquierda, derecha, abajo, o incluso arriba), puede alterar el orden de presentación de forma dinámica, es decir, que aparezcan antes o después con independencia de cómo estén en el html) y adaptar su tamaño y posición como respuesta al espacio disponible. Y si el elemento es multilínea comportarse como lo hace el texto de varias líneas.

Aviso y Disclaimer:
Los ejemplos utilizados sólo incluyen los prefijos privativos -moz- y -webkit- ya sabes lo que eso significa. Las distintas propiedades del flexbox se utilizan con el prefijo box- (ejemplo: box-order) que es funcional en los navegadores indicados, pese a que en el último documento del consorcio W3c CSS Flexible Box Layout Module el utilizado es flex- (ejemplo: flex-order).
Así mismo, la propiedad es declarada como display: flexbox;
Con bastante posterioridad, Css-tricks publica una nota explicativa: “Old” Flexbox and “New” Flexbox

Vale, está muy bien esta declaración de intenciones, pero la cuestión es ¿ésto cómo se come? O dicho de otra forma: ¿ventajas?
Algunas:

  • Adios a los floats, inline-block, magin: 0 auto; y otras cuantas cosillas para maquetaciones complejas.
  • Estructuras que hasta ahora parecían inabordables o imposibles son pan comido. Sin necesitar de otros lenguajes (como js) para las adaptaciones al vuelo.
  • Expresiones como diseño adaptable, líquido, porcentual... pasan a la historia y los cálculos y planteamientos previos que tenías que hacer ahora los hace el navegador por ti.

El ejemplo del textarea (by Paul Irish), dejando de lado los estilos de tamaños y colores, el centrado dinámico y simultáneo en X e Y está logrado con los códigos siguientes. Compara con lo que era necesario hasta ahora.

<div class="center-box-flex"> <textarea> redimensióname </textarea> </div>
.center-box-flex { display: box; box-orient: horizontal; box-pack: center; box-align: center; }

¿Qué es la flexibilidad en Css en el Flexible Box Model Layout

En palabras de Paul Irish:

La propiedad box-flex determina si un elemento secundario (hijo) de una caja flexible debe ser flexible o no y ayuda a definir su grado de flexibilidad en relación con el resto de elementos secundarios (sus hermanos).

El valor Box para la propiedad display

Todo esto se consigue con un único valor añadido a la propiedad display: box y unas pocas propiedades nuevas relacionadas con él. En concreto 8 y una más que agrupa a 2 de ellas.
No es tanto lo que hay que aprender vistas las ventajas que ofrece, creo.

Lo que conlleva el modelo de caja flexible:

En el elemento padre: el FlexBox

El modelo de caja flexible (flexbox) sólo se aplica a la caja padre a la que se declara y a sus hijos. Esto es, la herencia sólo llega a la primera generación (hijos). A estos hijos los llamaremos items. Los elementos contenidos por los items (sus descendientes) no se ven afectados, no heredan.

FlexBox utiliza un nuevo algoritmo de diseño, por lo que algunas de las propiedades que fueron diseñadas con el modelo de caja tradicional (Css2.1) no tienen sentido en un contexto FlexBox. En particular:

  • Todas las propiedades del módulo "column-*" no aplican.
  • "Float" y "clear" no tienen efecto en los items. Si se declara "float" en un elemento padre causa que la propiedad "display" se compute como "block", porque esto ocurre antes de procesar el flexbox en los items (el algoritmo para tratar a los hijos de un FlexBox como items de FlexBox necesita el que el valor calculado de "display" sea "flexbox").
  • "vertical-align" no tiene ningún efecto sobre la alineación de un elemento FlexBox en el modelo flexible.
  • Si el valor especificado en un elemento de 'display' es 'inline-FlexBox' y el elemento es flotante o con posición absoluta, el valor computado de 'display' debe ser 'FlexBox'.

Y otras cuestiones son relativas. En Css2.1 los elementos de línea o flotados por defecto rellenan el eje X (horizontal) antes de pasar a la siguiente línea. En el flexbox este apilamiento se realizará en el eje principal (main axis) que será el marcado por la orientación declarada en box-orient. Y el eje secundario (cross axis) será el perpendicular a él.

En los hijos del FlexBox: los items

Los hijos de las cajas Flexbox deben cumplir también alguna de las siguientes condiciones:

  • Ser hijo directo de una caja flexbox
  • Los items de línea generan una caja anónima de bloque que los contiene para ser convertirdos en item y aplicarles las propiedades Flexbox.
  • Los elementos de bloque contenidos en estos items de línea procesados ya no son considerados item del FlexBox

Posíblemente esto último sea más comprensible con un código html de ejemplo:

<div style="display:flexbox"> <!-- flexbox item: es un elemento de bloque --> <div id="item1">block</div> <!-- no es flexbox item, está fuera del flujo por position --> <div id="not-an-item1.5" style="position: absolute;">block</div> <!-- flexbox item: elemento de bloque --> <div id="item2" style="display:table">table</div> <!-- flexbox item: se crea una tabla anónima envolviendo a table-cell --> <div id="item3" style="display:table-cell">table-cell</div> <!-- flexbox item: se crea caja de bloque anónima conteniendo el texto (elemento de línea) --> anonymous item 4 <span id="item6.1"><!-- flexbox item: caja de bloque anónima conteniendo el span (elemento de línea) --> text 6.2 <div id="not-an-item6.3">block</div><!-- no es flexbox item, es nieto --> text 6.4 </span> <!-- flexbox item: elemento de línea flotado que es cambiado a block (caja anónima)--> <span id="item10" style="float: left;">span</span> </div>

Observa lo resaltado en negrita: el elemento "not-an-item6.3" NO es un item (elemento del flexbox y al que se apliquen las propiedades correspondientes) porque es nieto. Al estar dentro de un elemento de línea que generó una caja de bloque y así convertirse en item.
Lo mismo para el "not-an-item1.5". NO es item. La razón en este caso es que pese a ser hijo del FlexBox está fuera del flujo por su posición absoluta

Soporte de los navegadores al FlexBox

En este momento mira la imagen. Blanco y gris soportado total o parcialmente y siempre con los respectivos prefijos privativos. Rojo no soportado. Verde desconocido. La imagen es captura de la página caniuse, a la que te remito para comprobar el estado actual.

Los siguientes ejemplos ilustrativos de las propiedades del FlexBox originales de Jérémie Patonnier, vía hacks.mozilla.org. Estos ejemplos comparten el mismo css básico para los estilos ornamentales (colores) y el html es siempre el mismo.

<div id="exemple1" class="block"> <div class="content"> <div class="boite v1">1</div> <div class="boite v2">2</div> <div class="boite v3">3</div> </div> </div>

Propiedades del modelo de caja flexible (flexbox) y sus Items

display: box
Valores: flexbox | inline-flexbox
Este nuevo valor para la propiedad display habilita en el elemento y sus items el Flexible Box Model. El valor 'FlexBox' hace al elemento de bloque. "Inline-flexbox' lo convierte en un elemento a nivel de línea respecto a sus hermanos.
Ordenamiento y orientación

Los items son, por defecto, presentados en pantalla en el mismo orden que aparecen en el documento origen (el html procesado). Esta presentación puede ser alterada con la propiedad flex-order. Bye, bye!! flotados, clear, posiciones absolutas... Hi!! equal columns, distribuciones equitativas, reparto de espacios sobrantes a voluntad...

box-orient
orient: horizontal
1
2
3
Valores: horizontal | vertical | inherit
Define cómo se deben alinear los items. Hay dos valores adicionales (inline-axis, el valor real predeterminado, y block-axis), pero se asignan a la orientación horizontal y vertical, respectivamente.
box-order
Vertical y orden alterado
1
2
3
Valores: numéricos.
El FlexBox colocará sus items de menor a mayor valor del "flex-order". Los items que tengan el mismo valor se dibujan de acuerdo a cómo aparezcan en el documento origen.
"Flex-order" no afecta al apilamiento vertical (eje Z) definido por z-index.
box-direction
Vertical y Reverse
1
2
3
Valores: row | row-reverse | column | column-reverse
Indica cómo son colocados los items en su FlexBox respecto al eje principal. Esto afecta a la dirección en la que los items se disponen, y el significado de la propiedad 'flex-pack'. ¿Recuerdas la propiedad "direction" de Css2.1 y sus Valores (ltr | rtl | inherit)?
Row: El eje principal se conforma en una línea horizontal (filas). En nuestra cultura el sentido de flujo es de izquierda a derecha
Row-reverse: Lo mismo que el anterior, pero cambiando el sentido del flujo. Si "row" es ltr, reverse será rtl.
Column: El eje principal será vertical, formando un apilamiento vertical de los items (columna). El sentido de flujo en nuestra columna es de arriba a abajo.
column-reverse: equivalente a "row-reverse" pero en la vertical.
Reparto del tamaño del flexbox entre sus items: Box-flex
(1)Tamaños flexibles
1
2
3

De forma predeterminada, los items de las cajas flexibles se mantienen inflexibles. Esto facilita que sea el diseñador a voluntad quien defina qué items y en qué medida se reparten el espacio libre del flexbox. Los items sólo se hacen flexibles a lo largo del eje principal de la caja.

(2)Box 3 noflexible width: 100px
1
2
3

En el ejemplo (1) de la derecha , la caja 1 tiene un valor de 2, la segunda no declarado (0) y la tercera de 1. Y en el siguiente (2) en la primera box-flex=3, en la segunda de 1 y la tercera una anchura fija en px.

box-flex
Valores: 0 | Un número entero
(3)box-flex no declarado=0
1
2
3
Indica el índice de flexibilidad del item. Si el valor de un item es 1 y el de otro es 2, este último ocupará el doble de espacio adicional de la caja principal. El valor predeterminado es 0, lo que indica que no es flexible.
Una o multiple líneas

En el FlexBox podemos definir si los items se disponen en una sola línea o en múltiples. Es controlado por la propiedad "box-wrap". Si es sólo 1 línea, los items podrán desbordar al Flexbox. Si es en múltiples se acomodan como lo hacen las líneas de texto de un párrafo.

box-wrap
Valores: nowrap | wrap | wrap-reverse
nowrap: el Flexbox genera una sóla línea.
wrap: Los items se acomodan en varias líneas si fuera necesario.
wrap-reverse: lo mismo que "nowrap", pero invirtiendo el sentido de colocación de los items.
Box-flow: Propiedad resumida (shorthand) de Direction y Wrap
box-flow
Valores: <'box-direction'> || <'box-wrap'>
Es la forma acortada de definir las propiedades direction y wrap.
Alineación (align) de los items en el Flexbox:

El 17 de Mayo de 2.012 fue publicado el documento CSS Box Alignment Module Level 3 que modifica algún aspecto de éste: `align-outside´ sustituye a ‘flex-item-align’. ‘align-inside’ sustituye a ‘flex-line-pack’. ‘align-items’ a ‘flex-align’.

Unas líneas arriba mencioné de pasada que la propiedad vertical-align no aplica en el flexbox. Sin embargo esta ordenación de los items se vuelve mucho más sencilla y con más valores de los recogidos en Css2.1.
Recuerda que siempre hay que tener presente cuál es el eje principal (el definido por box-orient), porque es en el en el que se realizan las alineaciones.

box-pack
Valores: start | end | center | justify
Define la alineación de los items a lo largo del eje definido por box-orient. Por tanto, si la orientación definida por box-orient es horizontal, esta propiedad determinará la forma de alineación horizontal de los items, y viceversa. Valor inicial: start.
El significado de los valores es obvio. Puedes verlos en la imagen adjunta.
box-align
Valores: start | end | center | baseline | stretch
Básicamente, es la propiedad secundaria de box-pack. Define la forma de alineación de los items en su línea (en el caso de tener tamaños dispares) en el eje secundario (perpendicular al principal). Si la orientación es horizontal (eje X), esta propiedad determinará la alineación vertical (en el eje Y), y viceversa. Valor inicial: stretch.
box-item-align
Valores: auto | start | end | center | baseline | stretch
Valor inicial: auto. Similar a box-align pero para ser declarado a cada item en paricular, modificando la aleneación de dicho item sobre el eje principal de la línea a la que pertenezca.
box-line-pack
Valores: start | end | center | justify | distribute | stretch
Define cómo alinea cada línea formada en el flexbox en su eje principal (el definido por box-orient). Es similar a box-pack, pero referida a las líneas dentro de la caja flexible, no los items en cada línea formada. Valor inicial: stretch.

Créditos, atribuciones, documentos relacionados y otros apuntes finales:

He procurado poner la autoría y fuente tanto de los códigos como de artículos en los que me he basado o inspirado para escribir este ejemplo. Pero por si acaso, aquí van otra vez.

Documento de referencia y base de este artículo: CSS Flexible Box Layout Module. Autor: W3c. Estado: Editor's Draft. Fecha documento: 16 de Marzo de 2012.
Estatus del último documento del consorcio: W3C Working Draft, 12 June 2012.
Especialmente de ayuda han sido diversos artículos publicados por Paul Irish en distintas páginas.
Los ejemplos en código con los que ilustro las distintas propiedades son obra de Jérémie Patonnier. Llegué a ellos vía hacks.mozilla.org.
Las imágenes ilustrativas de las últimas propiedades obtenidas de la documentación de la W3c.

Licencias

Todas la documentación utilizada para esta guía está basada en trabajos con licencia CC-by. Así que por coherencia y convencimiento propio la licencia es igual: CC {atribución, compartir igual, no comercial}

Tu turno

Si has llegado hasta aquí abajo te ganaste el derecho a dejar tu opinión en los comentarios. Que seguro que algo hay mal hecho o dicho y es tu deber corregirlo ;-)

Generador online

Alex Aguiar (gracias) en los comentarios comparte esta página donde no sólo encontrarás enlaces a artículos, ejemplos y realizaciones basadas en el flexbox, sino también un generador en línea de códigos y sus efectos.

avatar del Editor del blog

the obCSServer ᛯ Ramajero Argonauta, Enredique Amanuense de CSS.
#impoCSSible inside
Dicen que, en español, EsCss es el mejor blog de CSS. Posíblemente exageren.
@Kseso EsCss Kseso