Caja flexible

El podcast de CSS - 010: Flexbox

Un patrón de diseño que puede ser complicado en un diseño responsivo es una barra lateral intercalada con algún contenido. Donde hay espacio de viewport, este patrón funciona muy bien, pero cuando el espacio se condensa, ese diseño rígido puede convertirse en un problema.

El modelo de diseño de cuadro flexible (flexbox) es un modelo de diseño diseñado para contenido unidimensional. Se destaca por tomar muchos elementos de diferentes tamaños y mostrar el mejor diseño para esos elementos.

Este es el modelo de diseño ideal para este patrón de barra lateral. Flexbox no solo ayuda a ubicar la barra lateral y el contenido intercalados, sino que, cuando no hay suficiente espacio restante, la barra lateral se abrirá en una línea nueva. En lugar de establecer dimensiones rígidas para que el navegador las siga, con flexbox, puedes proporcionar límites flexibles para sugerir cómo podría mostrarse el contenido.

¿Qué puedes hacer con un diseño flexible?

Los diseños flexibles tienen las siguientes características, que podrás explorar en esta guía.

  • Se pueden mostrar como una fila o una columna.
  • Respetan el modo de escritura del documento.
  • De forma predeterminada, son una sola línea, pero se le puede pedir que se ajusten a varias líneas.
  • Los elementos del diseño se pueden reordenar visualmente, lejos de su orden en el DOM.
  • El espacio se puede distribuir dentro de los elementos, por lo que se hacen más grandes y pequeños según el espacio disponible en su elemento superior.
  • El espacio se puede distribuir entre los elementos y las líneas flexibles en un diseño unido mediante las propiedades de alineación de cuadros.
  • Los elementos en sí se pueden alinear en el eje cruzado.

El eje principal y el eje cruzado

La clave para entender flexbox es entender el concepto de un eje principal y un eje cruzado. El eje principal es el que establece tu propiedad flex-direction. Si es row, el eje principal está a lo largo de la fila; si es column, el eje principal está junto a la columna.

Tres cuadros uno al lado del otro con una flecha que apunta de izquierda a derecha. La flecha está etiquetada como eje principal.

Los elementos flexibles se mueven como un grupo en el eje principal. Recuerden: tenemos un montón de elementos y estamos tratando de obtener el mejor diseño para ellos como grupo.

El eje cruzado se ejecuta en la dirección opuesta al eje principal, por lo que, si flex-direction es row, el eje cruzado se ejecuta a lo largo de la columna.

Tres cuadros de diferentes alturas, uno al lado del otro con una flecha, que apunta de izquierda a derecha. La flecha se denomina Eje principal. Hay otra flecha que apunta de arriba abajo. Esta está etiquetada como "Eje cruzado"

Puedes realizar dos acciones en el eje cruzado. Puedes mover los elementos de forma individual o como grupo para que se alineen entre sí y con el contenedor flexible. Además, si uniste líneas flexibles, puedes tratarlas como un grupo para controlar cómo se les asigna el espacio. En esta guía, verás cómo funciona todo esto en la práctica. Por ahora, solo ten en cuenta que el eje principal sigue tu flex-direction.

Crea un contenedor flexible

Veamos cómo se comporta flexbox tomando un grupo de elementos de diferentes tamaños y usando flexbox para distribuirlos.

<div class="container" id="container">
  <div>One</div>
  <div>Item two</div>
  <div>The item we will refer to as three</div>
</div>

Para usar Flexbox, debes declarar que deseas usar un contexto de formato flexible y no un bloque normal ni un diseño intercalado. Para ello, cambia el valor de la propiedad display a flex.

.container {
  display: flex;
}

Como aprendiste en la guía de diseño, esto te proporcionará una caja a nivel de bloque, con elementos secundarios flexibles. Los elementos flexibles comienzan a mostrar de inmediato algún comportamiento de flexbox, mediante sus valores iniciales.

Los valores iniciales significan lo siguiente:

  • Los artículos se muestran como una fila.
  • No se unen.
  • No crecen para llenar el contenedor.
  • Se alinean al comienzo del contenedor.

Controlar la dirección de los elementos

Aunque aún no hayas agregado una propiedad flex-direction, los elementos se muestran como una fila porque el valor inicial de flex-direction es row. Si quieres una fila, no necesitas agregar la propiedad. Para cambiar la dirección, agrega la propiedad y uno de los cuatro valores:

  • row: Los elementos se disponen como una fila.
  • Con row-reverse:, los elementos se disponen como una fila desde el final del contenedor flexible.
  • column: Los elementos se disponen como una columna.
  • column-reverse : Los elementos se disponen como una columna desde el final del contenedor flexible.

Puedes probar todos los valores con nuestro grupo de elementos en la siguiente demostración.

Cómo revertir el flujo de elementos y la accesibilidad

Debes tener cuidado cuando uses cualquier propiedad que reordene la presentación visual en lugar del orden de los elementos en el documento HTML, ya que puede afectar la accesibilidad de forma negativa. Los valores row-reverse y column-reverse son un buen ejemplo de esto. El reordenamiento solo ocurre para el orden visual, no el lógico. Es importante comprender esto, ya que el orden lógico es el orden en que un lector de pantalla leerá el contenido, y lo seguirá cualquier persona que navegue con el teclado.

En el siguiente video, puedes ver cómo en un diseño de fila invertida se desconecta el tabulador entre vínculos a medida que la navegación con el teclado sigue el DOM, no la pantalla visual.

Cualquier cosa que pueda cambiar el orden de los elementos en flexbox o en la cuadrícula puede causar este problema. Por lo tanto, cualquier reordenamiento debe incluir pruebas exhaustivas que verifiquen que no dificultará el uso del sitio para algunas personas.

Para obtener más información, consulta:

Modos y dirección de escritura

Los elementos flexibles se muestran como una fila de forma predeterminada. Una fila se ejecuta en la dirección en la que las oraciones fluyen en el modo de escritura y la dirección de la secuencia de comandos. Esto significa que, si trabajas en árabe, que tiene una dirección de secuencia de comandos de derecha a izquierda (rtl), los elementos se alinearán a la derecha. El orden de tabulación también empezaría a la derecha, ya que esta es la forma en que las oraciones se leen en árabe.

Si trabajas con un modo de escritura vertical, como algunos tipos de letra japoneses, se ejecutará una fila verticalmente, de arriba abajo. Intenta cambiar flex-direction en esta demostración, que usa un modo de escritura vertical.

Por lo tanto, el comportamiento predeterminado de los elementos flexibles está vinculado al modo de escritura del documento. La mayoría de los instructivos se escriben en inglés o en otro modo de escritura horizontal, de izquierda a derecha. Esto haría que sea fácil suponer que los elementos flexibles se alinean a la izquierda y se ejecutan horizontalmente.

Teniendo en cuenta el eje principal y el cruzado, además del modo de escritura, podría ser más fácil entender que hablemos de start y end en lugar de superior, inferior, izquierdo y derecho en Flexbox. Cada eje tiene un inicio y un final. El inicio del eje principal se conoce como inicio principal. Así que nuestros artículos flexibles se alinean inicialmente desde el principio. El final de ese eje es main-end. El inicio del eje cruzado es cross-start y el final cross-end.

Un diagrama etiquetado de los términos anteriores

Cómo unir elementos flexibles

El valor inicial de la propiedad flex-wrap es nowrap. Esto significa que, si no hay suficiente espacio en el contenedor, los elementos se desbordarán.

Es un contenedor flexible que contiene nueve elementos; los elementos se redujeron, por lo que hay una palabra en una línea, pero no hay suficiente espacio para mostrarlos uno al lado del otro, por lo que los elementos flexibles se extendieron fuera de la caja del contenedor.
Una vez que alcancen el tamaño mínimo de contenido, los elementos flexibles comenzarán a desbordarse del contenedor.

Los elementos que se muestran con los valores iniciales se reducirán lo más pequeños posible, hasta el tamaño min-content antes de que se produzca el desbordamiento.

Para hacer que los elementos unan, agrega flex-wrap: wrap al contenedor flexible.

.container {
  display: flex;
  flex-wrap: wrap;
}

Cuando un contenedor flexible se une, crea varias líneas flexibles. En términos de distribución del espacio, cada línea actúa como un nuevo contenedor flexible. Por lo tanto, si unes filas, no es posible obtener algo en la fila 2 que se alinee con algo superior en la fila 1. Esto es lo que significa que Flexbox sea unidimensional. Puedes controlar la alineación en un eje, una fila o una columna, no ambos juntos como lo hacemos en la cuadrícula.

La abreviatura del flujo flexible

Puedes configurar las propiedades flex-direction y flex-wrap con la abreviatura flex-flow. Por ejemplo, para establecer flex-direction en column y permitir que los elementos se unan:

.container {
  display: flex;
  flex-flow: column wrap;
}

Cómo controlar el espacio en elementos flexibles

Si suponemos que nuestro contenedor tiene más espacio del necesario para mostrar los elementos, estos se alinean al principio y no crecen para llenar el espacio. Dejan de crecer al máximo de contenido. Esto se debe a que el valor inicial de las propiedades de flex- es el siguiente:

  • flex-grow: 0: Los elementos no crecen.
  • flex-shrink: 1: Los elementos pueden reducirse a un tamaño más pequeño que su flex-basis.
  • flex-basis: auto: Los elementos tienen un tamaño base de auto.

Esto se puede representar con un valor de palabra clave de flex: initial. La propiedad abreviada flex o las combinaciones de teclas de flex-grow, flex-shrink y flex-basis se aplican a los elementos secundarios del contenedor flexible.

Para hacer que los elementos crezcan, y permitir que los elementos grandes tengan más espacio que los pequeños, usa flex:auto. Puedes probar esto con la demostración anterior. Esto establece las propiedades de la siguiente manera:

  • flex-grow: 1: Los elementos pueden ser más grandes que su flex-basis.
  • flex-shrink: 1: Los elementos pueden reducirse a un tamaño más pequeño que su flex-basis.
  • flex-basis: auto: Los elementos tienen un tamaño base de auto.

Usar flex: auto implicará que los elementos terminen en diferentes tamaños, ya que el espacio compartido entre los elementos se comparte después de que cada uno se presenta como tamaño máximo de contenido. Por lo tanto, un elemento grande ganará más espacio. Para forzar que todos los elementos tengan un tamaño coherente e ignorar el tamaño del contenido, cambia flex:auto a flex: 1 en la demostración.

Esta acción se desempaqueta en:

  • flex-grow: 1: Los elementos pueden ser más grandes que su flex-basis.
  • flex-shrink: 1: Los elementos pueden reducirse a un tamaño más pequeño que su flex-basis.
  • flex-basis: 0: Los elementos tienen un tamaño base de 0.

El uso de flex: 1 indica que todos los elementos tienen tamaño cero, por lo que todo el espacio en el contenedor flexible está disponible para distribuirse. Como todos los elementos tienen un factor flex-grow de 1, todos crecen por igual y el espacio se comparte por igual.

Permite que los elementos crezcan a diferentes velocidades.

No debes asignar a todos los elementos un factor flex-grow de 1. Podrías asignar diferentes factores flex-grow a tus elementos flexibles. En la demostración que aparece a continuación, el primer elemento tiene flex: 1, el segundo flex: 2 y el tercero flex: 3. A medida que estos elementos aumentan a partir de 0, el espacio disponible en el contenedor flexible se comparte en seis. Se le da una parte al primer elemento, dos partes al segundo y tres partes al tercero.

Puedes hacer lo mismo desde un flex-basis de auto, aunque deberás especificar los tres valores. El primer valor es flex-grow, el segundo flex-shrink y el tercer valor flex-basis.

.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

Este es un caso de uso menos común, ya que el motivo para usar un flex-basis de auto es permitir que el navegador determine la distribución del espacio. Si quisieras hacer que un elemento crezca un poco más de lo que decide el algoritmo, podría ser útil.

Reordenando elementos flexibles

Los elementos del contenedor flexible se pueden reordenar con la propiedad order. Esta propiedad permite ordenar los elementos en grupos ordinales. Los elementos se disponen en la dirección dictada por flex-direction, primero los valores más bajos. Si más de un artículo tiene el mismo valor, se mostrará junto con los demás que tengan ese valor.

En el siguiente ejemplo se demuestra este orden.

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre Flexbox

El valor predeterminado de flex-direction es

row
De forma predeterminada, Flexbox colocará los elementos en una fila y los alineará al principio. Si la unión está activada, se seguirán creando filas para que los elementos secundarios fluyan.
column
Establecer la dirección flexible en la columna es una excelente manera de apilar elementos, pero no es el valor predeterminado.

De forma predeterminada, un contenedor flexible une los elementos secundarios.

true
La unión debe estar habilitada.
false
Usa flex-wrap: wrap con display: flex para unir los elementos secundarios

Un elemento secundario de Flex aparece aplastado, ¿qué propiedad de Flex ayuda a mitigarlo?

flex-grow
Esta propiedad describe si los elementos pueden crecer más allá de un tamaño de base, no cómo debe comportarse sobre una base.
flex-shrink
Sí, en esta propiedad se describe cómo manejar el tamaño si el ancho es inferior a la base.
flex-basis
Esto proporciona el punto de partida para el tamaño, pero no cómo manejar situaciones de tamaño en las que el ancho es inferior a la base, como en una situación aplastada.

Descripción general de la alineación de Flexbox

Flexbox incorporó un conjunto de propiedades para alinear elementos y distribuir espacio entre ellos. Estas propiedades fueron tan útiles que se trasladaron desde entonces a su propia especificación que también las encontrarás en Grid Layout. Aquí puedes ver cómo funcionan cuando usas Flexbox.

El conjunto de propiedades se puede ubicar en dos grupos. Propiedades de la distribución del espacio y propiedades de la alineación. Las propiedades que distribuyen el espacio son las siguientes:

  • justify-content: Distribución de espacios en el eje principal
  • align-content: La distribución del espacio en el eje cruzado.
  • place-content: Es una abreviatura para configurar las dos propiedades anteriores.

Estas son las propiedades que se usan para la alineación en flexbox:

  • align-self: Alinea un solo elemento en el eje cruzado.
  • align-items: Alinea todos los elementos como un grupo en el eje cruzado.

Si estás trabajando en el eje principal, las propiedades comienzan con justify-. En el eje cruzado, comienzan con align-.

Distribución del espacio en el eje principal

Con el HTML que se usó antes, los elementos flexibles dispuestos en fila, hay espacio en el eje principal. Los elementos no son lo suficientemente grandes como para llenar el contenedor flexible por completo. Los elementos se alinean al comienzo del contenedor flexible porque el valor inicial de justify-content es flex-start. Los elementos se alinean al principio y cualquier espacio adicional está al final.

Agrega la propiedad justify-content al contenedor flexible y asígnale un valor de flex-end. Los elementos se alinearán al final del contenedor y el espacio libre se colocará en el comienzo.

.container {
  display: flex;
  justify-content: flex-end;
}

También puedes distribuir el espacio entre los elementos con justify-content: space-between.

Prueba algunos de los valores de la demostración y consulta MDN para ver el conjunto completo de valores posibles.

Con flex-direction: column

Si cambiaste tu flex-direction a column, justify-content funcionará en la columna. Para tener espacio libre en el contenedor cuando trabajas como columna, debes otorgarle un height o block-size. De lo contrario, no tendrás espacio libre para distribuir.

Prueba los diferentes valores, esta vez con un diseño de columnas de flexbox.

Distribución del espacio entre las líneas flexibles

Con un contenedor flexible unido, es posible que haya espacio para distribuir en el eje cruzado. En este caso, puedes usar la propiedad align-content con los mismos valores que justify-content. A diferencia de justify-content, que alinea los elementos con flex-start de forma predeterminada, el valor inicial de align-content es stretch. Agrega la propiedad align-content al contenedor flexible para cambiar ese comportamiento predeterminado.

.container {
  align-content: center;
}

Pruébalo en la demostración. El ejemplo tiene líneas unidas de elementos flexibles y el contenedor tiene un block-size para que tengamos espacio libre.

La abreviatura place-content

Para configurar justify-content y align-content, puedes usar place-content con uno o dos valores. Se usará un solo valor para ambos ejes, si especificas que se usará el primero para align-content y el segundo para justify-content.

.container {
  place-content: space-between;
  /* sets both to space-between */
}

.container {
  place-content: center flex-end;
  /* wrapped lines on the cross axis are centered,
  on the main axis items are aligned to the end of the flex container */
}

Alinear elementos en el eje cruzado

En el eje cruzado también puedes alinear tus elementos dentro de la línea flexible mediante align-items y align-self. El espacio disponible para esta alineación dependerá de la altura del contenedor flexible, o de la línea flexible en el caso de un conjunto de elementos unido.

El valor inicial de align-self es stretch, por lo que los elementos flexibles en una fila se extienden hasta la altura del elemento más alto de forma predeterminada. Para cambiar esto, agrega la propiedad align-self a cualquiera de tus elementos flexibles.

.container {
  display: flex;
}

.item1 {
  align-self: flex-start;
}

Usa cualquiera de los siguientes valores para alinear el elemento:

  • flex-start
  • flex-end
  • center
  • stretch
  • baseline

Consulta la lista completa de valores en MDN.

La siguiente demostración tiene una sola línea de elementos flexibles con flex-direction: row. El último elemento define la altura del contenedor flexible. El primer elemento tiene la propiedad align-self con un valor de flex-start. Intenta cambiar el valor de esa propiedad para ver cómo se mueve dentro de su espacio en el eje cruzado.

La propiedad align-self se aplica a elementos individuales. La propiedad align-items se puede aplicar al contenedor flexible para establecer todas las propiedades individuales align-self como un grupo.

.container {
  display: flex;
  align-items: flex-start;
}

En la siguiente demostración, intenta cambiar el valor de align-items para alinear todos los elementos del eje cruzado como un grupo.

¿Por qué no hay justificado en Flexbox?

Los elementos flexibles actúan como un grupo en el eje principal. Por lo tanto, no hay el concepto de dividir un elemento individual de ese grupo.

En el diseño de cuadrícula, las propiedades justify-self y justify-items funcionan en el eje intercalado para alinear los elementos en ese eje dentro de su área de cuadrícula. Debido a la forma en que los diseños flexibles tratan los elementos como un grupo, estas propiedades no se implementan en un contexto flexible.

Vale la pena saber que Flexbox funciona muy bien con los márgenes automáticos. Si necesitas dividir un elemento de un grupo o separar el grupo en dos, puedes aplicarle un margen. En el ejemplo a continuación, el último elemento tiene un margen izquierdo de auto. El margen automático absorbe todo el espacio en la dirección en la que se aplica. Esto significa que envía el elemento hacia la derecha y, por lo tanto, divide los grupos.

Cómo centrar un elemento de forma vertical y horizontal

Las propiedades de alineación se pueden usar para centrar un elemento dentro de otro cuadro. La propiedad justify-content alinea el elemento en el eje principal, que es la fila. La propiedad align-items en el eje cruzado.

.container {
  width: 400px;
  height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
}

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre Flexbox

.container {
  display: flex;
  direction: ltr;
}

Para alinear verticalmente con flexbox, usa

alinear palabras clave
Genial
justificar palabras clave
Afligido
.container {
  display: flex;
  direction: ltr;
}

Para alinearlo horizontalmente con Flexbox, usa

alinear palabras clave
Afligido
justificar palabras clave
Genial
.container {
  display: flex;
  direction: ltr;
}

De forma predeterminada, los elementos flexibles se alinean con stretch. Si quieres que el tamaño del contenido se use para elementos secundarios, ¿cuál de los siguientes estilos usarías?

justify-content: flex-start
La propiedad de justificación es para la alineación horizontal, no vertical.
align-content: start
content alinea las líneas flexibles, no la alineación del elemento secundario.
height: auto
Esta acción no tendrá ningún efecto.
align-items: flex-start
Sí, queremos alinearlos verticalmente con la parte superior o el inicio, lo que quita el valor de estiramiento predeterminado y usa la altura del contenido.

Recursos