soy Kseso y esto EsCSS

El nuevo Flexbox: flexible box model o modelo flexible de caja. Su layout

Un repaso en profundidad al flexbox o modelo de caja flexible (flexible box model layout). Ojo: usando la nomenclatura y sintaxis actual y vigente, no la antigua ya abandonada por el W3c

El nuevo Flexbox: flexible box model o modelo flexible de caja. Su layout

·Por Kseso ✎ 10

Última Actualización Marzo 2013

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 elementos en el documento origen.
A la vez muchas de las carencias de Css2.1 en el control de las cajas y realización del layout quedan superadas al utilizar el flexbox. Y otras muchas que requerían de ingenio y realizaciones complejas dejan de serlo.

Este artículo es complementario y actualización del ya veterano flexible box model layout escrito en Marzo de este año. Pero enfocado no tanto a trasladar al español el documento del consorcio sobre él sino a que tengas una visión global del flexbox y las posibilidades que trae. Te remito a él para ampliar conceptos y terminología.

Acércate a este modelo de caja sin pretender asimilarlo y dominarlo todo desde el principio. Haz como con con otros aspectos de Css como el box-shadow: primero supiste que se pueden hacer sombras, después descubrirte que puedes controlar hasta 6 aspectos en cada valor, y que puedes definir múltiples valores en la propiedad, y por fin alguien crea un script que reproduce cualquier imagen como la Monalisa y otros.

Ni que decir tiene que la nomenclatura y sintaxis que te vas a encontrar es la actual y no la antigua (ver “Old” Flexbox and “New” Flexbox” de Chris Coyier) y la base del artículo es el documento "CSS Flexible Box Layout Module" con estatus W3C Candidate Recommendation del 18 de Septiembre de este año.

Sumario

  1. Soporte de los navegadores al flexbox
  2. El concepto del Flexbox
  3. Terminología o vocabulario del flexbox
  4. Propiedades del Flexbox model
  5. Propiedades que no aplican al flexbox
  6. Cómo crear un flexbox
  7. Ejemplos de uso e ilustrativos de cómo funciona el flexbox
  8. Artículos relacionados

Soporte de los navegadores 03/2013

  • Opera (12.1) - Soporta la última especificación sin necesidad de prefijos privativos.
  • Chrome (23.0) - Soporta la última especificación pero necesita su prefijo privativo -webkit-.
  • Safari (5.1) - Soporta la vieja especificación pero necesita su prefijo privativo -webkit-.
  • Internet Explorer (10) - Soporta la vieja especificación pero necesita su prefijo privativo -ms-. IE9 y menores no le dan soporte
  • Firefox (16.0) - Soporta la vieja especificación pero necesita su prefijo privativo -moz-. La versión 20.0 soportará la última especificación sin necesidad de prefijos.

El concepto de Flexbox o caja flexible

Las principales características que definen el diseño flexible son:

  • El orden de colocación de los items en la pantalla es independiente del orden de aparición en el Html.
  • Los items se liberan de la tiranía de la propiedad direction y unicode-bidi. Esto es:
    • La noción de ejes X e Y y su obligado seguimiento queda superado.
    • La capacidad de alterar los tamaños de los elementos para rellenar mejor el espacio disponible en cualquier dispositivo de visualización. Una caja flexible expande sus items para llenar el espacio libre disponible, o los reduce para que no haya desbordamientos.
  • Otras que tú mismo descubrirás tras jugar con él.

Terminología o vocabulario del flexbox

Debido a que ideas, conceptos y comportamientos establecidos hasta ahora quedan obsoletos o no son de aplicación y que el modelo de caja flexible introduce otros nuevos es conveniente familiarizarse con su terminología.
Para comprenderla mejor, apóyate en el gráfico de abajo:

nuevo flexbox
Flexibilidad
Es la capacidad de una caja (flex container) para hacer que sus hijos (flex items) modifiquen sus tamaños para llenar el espacio disponible. Y a la vez distribuir el espacio sobrante entre ellos, alterando, si fuera necesario, las medidas de los items para evitar desbordes o colapsos.
Simultáneamente a lo anterior, la flexibilidad permite establecer qué eje (X-Y) es el principal y cuál es el sentido de flujo de los items en ambos ejes.
Así mismo, la flexibilidad permite alterar el orden de presentación de los items con independencia del lugar que ocupan en el html.
Flex container:
La caja contenedora o padre de los elementos flexibles. Para que un elemento se convierta en "flex container" hay que declarar la propiedad display con el valor flex o inline-flex. Más en detalle.
No confundas el valor flex de la propeidad display que se declara en al flex container con la propiedad acortada flex que se usa en los items.
Flex items
Son los hijos del flex container y sobre los que se aplicará el flexible box model layout. El texto contenido diréctamente en un flex container se envuelve en un flex item anónimo. Pero si el texto es únicamente espacio en blanco no se renderiza, se trata como si tuviese "display: none".
Para ver exáctamente cuándo un elemento se convierte en un flex item y cuando no lee esto.
Axis o ejes
En cada flex container se definen dos ejes. El eje principal o main axis es el eje a lo largo de la cual los items se ordenan en líneas (ya sean filas o columnas, dependendiente de que sea el eje X o Y el definido como principal). El eje transversal o cross axis es el eje perpendicular al eje principal.
  • La propiedad flex-direction define o marca la dirección del eje principal.
  • La propiedad justify-content alinea todos los items de la línea actual a lo largo del eje principal.
  • La propiedad align-items hace la misma alineación que justify-content pero en el eje transversal. Y la propiedad align-self alinea en el eje transversal los items de manera individual, reescribiendo el valor de "align-items" para ese hijo en concreto.
Direcciones o sentido de colocación
Main start/end y cross start/end. La colocación de los items en cada una de las líneas de los dos ejes se pueden ordenar en un sentido u otro de la dirección de cada eje. Si el eje principal es el horizontal (X) se pueden colocar de derecha a izquierda o de izquierda a derecha formando filas. Y si el main axis es el vertical (Y) forman columnas de arriba a abajo o al contrario.
Líneas
Los items pueden ser distribuidos en una sólo línea o en varias dentro de su container con la propiedad flex-wrap.
Tamaños o dimensiones
En los items no tiene sentido, por lo anterior, hablar de anchuras o alturas (width/height). Sus equivalentes son el "main size" y "cross size" que siguen (orientan) de acuerdo al eje principal y transversal.
  • Las propiedades min-height y min-width tienen un nuevo valor: auto que establece el tamaño mínimo del item.
  • Flex es la forma acortada de las propiedades que establecen la "flexibilidad" de una caja y sus items.

Propiedades del Flexbox model

A continuación un listado por orden alfabético de las propiedades necesarias para poder usar el nuevo modelo de caja flexible. Son las que controlan todos los aspectos del flexbox o modelo flexible de caja. Recuerda que ésta es la sintaxis actual. Mi opinión es que es la que deberías manejar, con independencia del soporte actual de los navegadores.
No se preveen cambios significativos, por el estatus que te comenté al inicio (candidata para ser la recomendación).

Indico entre (paréntesis e itálicas) a qué elemento se aplica la propiedad seguido de los valores posibles. En los enlaces (que dirigen a la página developer.mozilla.org) de cada una tienes toda la información de ella: los valores admitidos, su significado o qué hacen, el soporte por los diferentes navegadores a cada una, etc. Pincha en las imágenes que las acompañan para verlas bien.

align-content
align-content (flex containers que forman múltiples líneas). Valores: flex-start | flex-end | center | space-between | space-around | stretch
Define cómo se alinean las líneas formadas por los items dentro del contenedor flexible cuando hay espacio adicional en el eje transversal. El valor por defecto es "stretch" que hace a todos los items de la misma "altura" (columnas equilibradas por defecto).
align-items
align-items (flex container). Valores: flex-start | flex-end | center | baseline | stretch
Alinea los items su línea en la dirección perpendicular (eje transversal).
align-self
(items) Valores: auto | flex-start | flex-end | center | baseline | stretch
Alinea un item determinado sobreescribiendo el valor de "align-items"
display
(flex container) flex | inline-flex
Convierte un elemento en un flex container.
flex
flex (items) none | [ 'flex-grow' 'flex-shrink' || 'flex-basis' ]
Propiedad acortada de flex-basis, flex-grow y flex-shrink:
Son las que hacen posible y en qué forma y proporción los items modifican sus tamaños para ocupar y repartirse el espacio disponible en el flex container. O lo disminuyen para adaptarse a él.
  • flex-grow: Si hay espacio sobrante en el container determina cuánto de ese espacio ocupará el item respecto a los otros. Es una relación. Así, si tienes 100px sobrantes en el container y tres items con valores de 1, 1 y 2 en flex-grow, los dos primeros crecen 1 parte cada uno de los 100px = 25px cada uno [(100/4)*1], y el tercero 2 = 50px. También se le llama factor o relación de crecimiento.
  • flex-shrink: Los items además de poder crecer para repartirse el espacio libre del container también pueden encoger (disminuir su tamaño para evitar desbordes) cuando su flexbox no es lo suficientemente grande. Esta propiedad lo controla de la misma forma que flex-grow.
  • flex-basis: El tamaño inicial del item antes de crecer o disminuir en función del espacio de su flex container por las dos propiedades anteriores. Si se omite el valor es cero (0) y el valor "auto" significa que su tamaño está en función de su contenido.
flex-flow
flex-flow (flex container) Forma acortada de "flex-direction" y "flex-wrap":
  • flex-direction: row | row-reverse | column | column-reverse | Especifica cómo se colocan los items en el contenedor flexible definiendo el eje principal y la dirección (normal o invertida/reverse).
  • flex-wrap: nowrap | wrap | wrap-reverse | Define si los items se colocan en una o varias líneas
justify-content
justify-content (flex containers) Valores: flex-start | flex-end | center | space-between | space-around
Alinea los items en el eje principal de la línea actual. La alineación se realiza después de aplicar los tamaños y los márgenes de los items. Esta propiedad no tiene efecto en flex containers de una sola línea.
min-height y min-width
(elementos de bloque y reemplazados)
Valores para las dos: length | percentage | auto | max-content | min-content | fit-content | fill-available
Se usan para establecer la altura/anchura mínima de un elemento dado. Evita que el valor utilizado en height/width de cada item sea menor que el valor especificado para min-height/min-width. Interesante que veas cada una de las palabras clave usadas como valores.
order
(items) valores numéricos
Especifica el orden en que se dibujan los items en su container, con independencia de cómo aparezcan en el html. Los elementos se disponen en orden ascendente según su valor de "order". Los items con el mismo valor en "order" se presentan en el orden en que aparecen en el código fuente.

Propiedades que no aplican al flexbox

  1. Todas las column-* del módulo de las multicolumnas Css no hacen nada en un flex container.
  2. float y clear no tienen efecto en los items.
  3. vertical-align tampoco tiene efecto en los items.

Convertir una caja en un flex container

Lo primero que hay que hacer es indicar que un elemento cree una caja flexible o flexbox. Para ello se usa una de los dos declaraciones siguientes:

section {display: flex;}Crea un flexbox de bloque (block) article {display: inline-flex;}Crea un flex de línea (inline)

Ejemplos de uso e ilustrativos de cómo funciona el flexbox

Tengamos un html de lo más típico y normal: una página con su cabecera, su sección principal y el pie de página, tal como el siguiente:

<body> <header>header</header> <div id='main'> <article>article</article> <nav>nav</nav> <aside>aside</aside> </div> <footer>footer</footer> </body>

Lo siguiente es definir el Css para logar una caja flexible (en el ejemplo el div con id "main") y las propiedades para verse en un sobremesa. Fíjate que el orden en el html es article -> nav -> aside. No incluyo prefijos ni las propiedades "visuales". El resultado es la imagen al lado del css:

#main { min-height: 800px; /*creamos el flex container:*/ display: flex; /*Cómo se disponen los items:*/ flex-flow: row; /*row= el eje principal coincide con la dirección del texto. En español horizontal (eje Y) de Izq a drcha*/ } #main > article { flex: 3 1 60%; /*3= flex-grow = factor de crecimiento// 1= flex-shrink = factor de contracción // 60%= flex-basis = el espacio del container que ocupará el item*/ order: 2; /*2= se dibujará en segundo lugar, tras el item que tenga un valor de 1*/ } #main > nav { flex: 1 6 20%; order: 1; } #main > aside { flex: 1 6 20%; order: 3; }

El resultado de este css es el que puedes ver en la imagen de abajo. Es una captura de Chrome Canary. Como ves, se ha producido una ordenación de nav, article y aside respecto al html. Y lo mismo con las anchuras. Article ocupa el 60% del espacio de su padre y los otros dos un 20% cada uno. Y el factor de crecimiento de article es de 3 y el de merma 1. Mientras que en los otros estos valores está invertidos: 1 y 6

ejemplo gráfico de flexbox

Y a continuación definimos una media querie pensando en pantallas pequeñas.

@media all and (max-width: 640px) { #main, #page { flex-flow: column; /*cambiamos de filas a columnas*/ } #main > article, #main > nav, #main > aside { /* Restablecemos el orden */ order: 0; } #main > nav, #main > aside, header, footer { /*Fijamos alturas*/ min-height: 50px; max-height: 50px; } }

imagen ilustrativa flexboxEl resultado al ver la página en una ventana del tamaño definido cambia totalmente respecto al anterior: ahora los elementos están uno sobre otro, no al lado formando las 3 columnas. Hemos alterado el orden de "dibujado" de los elementos en la pantalla (order:0) para todos. Con el flexbox ahora podemos poner en el html en primer lugar el elemento principal de la página (article). Así se vería.

Animación de las propiedades flex

No todas las propiedades de este módulo admiten animaciones. Las que sí lo hacen son:
order
flex-grow, flex-shrink: excepto entre el valor 0 y otros
flex-basis: en la medida que lo es la propiedad width


Juega con el flexbox

Si quieres entretenerte un poco con estas propiedades, bájate Chrome Canary. Asegúrate de tener la última versión. Recuerda que debes utilizar los prefijos privativos.
Puedes pasarte por CSS Flexbox Please! o por flexplorer y prueba a variar los valores para ver en vivo qué hace qué y obtener los códigos.

Para cualquier detalle al respecto, nada como el documento del W3c. Aquí tienes de nuevo su enlace: CSS Flexible Box Layout Module. Siempre es bueno tener a mano la fuente original.

03/2013 : El artículo de Adobe en sus blogs "Working with flexbox: The new specification" [ing] tiene un .zip para descargar con ejemplos de realizaciones con el flexbox.

En codepen tienes alguna realización al respecto. Esta incluye la nueva nomenclatura:

En el pen, como ves, su autor comenta cada una de las propiedades y qué hace.

Y ya para terminar, que si has llegado hasta aquí ya tienes mérito, una colección de pens en la que tienes de todo un poco sobre el flexbox: nuevo y viejo/obsoleto.

Y fin

Si conoces otras demos realizadas con el flexbox compártelas en los comentarios. Y si descubres en el artículo algún error, omisión o algún dato poco riguroso házmelo saber. Gracias.

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