Caja flexible

Podcast de CSS - 010: Flexbox

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

El modelo de diseño de caja flexible (flexbox) es un modelo de diseño diseñado para contenido unidimensional. Destaca por tomar muchos elementos que tienen diferentes tamaños y mostrar el mejor diseño para ellos.

Este es el modelo de diseño ideal para este patrón de barra lateral. Flexbox no solo ayuda a colocar la barra lateral y el contenido intercalados, sino que, cuando no queda suficiente espacio, la barra lateral se divide 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 indicar cómo se podría mostrar 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 de una sola línea, pero se puede solicitar que se unan en varias líneas.
  • Los elementos del diseño se pueden reorganizar visualmente, sin importar su orden en el DOM.
  • El espacio se puede distribuir dentro de los elementos, de modo que se vuelvan más grandes o más pequeños según el espacio disponible en su elemento superior.
  • El espacio se puede distribuir alrededor de los elementos y las líneas flexibles en un diseño unido con las propiedades de alineación de cuadro.
  • Los elementos se pueden alinear en el eje transversal.

El eje principal y el eje transversal

La clave para comprender flexbox es entender el concepto de un eje principal y un eje transversal. El eje principal es el que establece tu propiedad flex-direction. Si es row, tu eje principal está a lo largo de la fila. Si es column, tu eje principal está a lo largo de 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. Recuerda: tenemos muchos elementos y estamos tratando de obtener el mejor diseño para ellos como grupo.

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

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

Puedes hacer dos cosas en el eje transversal. Puedes mover los elementos de forma individual o en grupo para que se alineen entre sí y con el contenedor flex. Además, si tienes líneas flexibles ajustadas, puedes tratarlas como un grupo para controlar cómo se asigna el espacio a esas líneas. Verás cómo funciona todo esto en la práctica a lo largo de esta guía. Por ahora, 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 diseñarlos.

<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 diseño intercalado ni de bloque normal. Para ello, cambia el valor de la propiedad display a flex.

.container {
  display: flex;
}

Como aprendiste en la guía de diseño, se mostrará un cuadro de nivel de bloque con elementos secundarios flexibles. Los elementos flex comienzan a mostrar inmediatamente un comportamiento de flexbox con sus valores iniciales.

Los valores iniciales significan lo siguiente:

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

Cómo 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 es necesario que agregues la propiedad. Para cambiar la dirección, agrega la propiedad y uno de los cuatro valores:

  • row: Los elementos se organizan en una fila.
  • row-reverse: Los elementos se organizan como una fila desde el final del contenedor de flex.
  • column: Los elementos se organizan como una columna.
  • column-reverse: Los elementos se organizan como una columna desde el final del contenedor de flex.

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

Invertir el flujo de elementos y accesibilidad

Debes tener cuidado cuando uses propiedades que reordenen la visualización visual lejos de cómo se ordenan los elementos en el documento HTML, ya que puede afectar negativamente la accesibilidad. Los valores row-reverse y column-reverse son un buen ejemplo de esto. El reordenamiento solo se produce para el orden visual, no para el orden lógico. Es importante comprender esto, ya que el orden lógico es aquel en el que un lector de pantalla leerá el contenido, y cualquier persona que navegue con el teclado lo seguirá.

En el siguiente video, puedes ver que, en un diseño de fila invertido, el tabulación entre los vínculos se desconecta cuando la navegación con teclado sigue el DOM, y no la visualización visual.

Cualquier elemento que pueda cambiar el orden de los elementos en flexbox o cuadrícula puede causar este problema. Por lo tanto, cualquier reordenamiento debe incluir pruebas exhaustivas para verificar que no haga que tu sitio sea difícil de usar para algunas personas.

Para obtener más información, consulta lo siguiente:

Modos y dirección de escritura

Los elementos flexibles se organizan como una fila de forma predeterminada. Una fila se ejecuta en la dirección en la que fluyen las oraciones en el modo de escritura y la dirección de la escritura. Esto significa que, si trabajas en árabe, que tiene una dirección de escritura 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 así es como se leen las oraciones en árabe.

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

Por lo tanto, el comportamiento predeterminado de los elementos flexibles se vincula al modo de escritura del documento. La mayoría de los instructivos están escritos en inglés o en otro modo de escritura horizontal de izquierda a derecha. Esto facilitaría suponer que los elementos flex se alinean a la izquierda y se ejecutan horizontalmente.

Con el eje principal y el eje transversal, además del modo de escritura que se debe tener en cuenta, es posible que sea más fácil comprender el hecho de que hablamos de inicio y final en lugar de arriba, abajo, izquierda y derecha en flexbox. Cada eje tiene un inicio y un final. El inicio del eje principal se denomina main-start. Por lo tanto, nuestros elementos flexibles se alinean inicialmente desde main-start. El extremo de ese eje es main-end. El inicio del eje transversal es cross-start y el final cross-end.

Un diagrama etiquetado de los términos anteriores

Cómo unir elementos flex

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.

Un contenedor flexible con nueve elementos en su interior. Los elementos se redujeron para que una palabra esté en una línea, pero no hay espacio suficiente para mostrarlos en paralelo, por lo que los elementos flexibles se extendieron fuera del cuadro del contenedor.
Una vez que alcancen el tamaño mínimo de contenido, los elementos flex comenzarán a desbordar su contenedor.

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

Para que los elementos se unan, agrega flex-wrap: wrap al contenedor de flex.

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

Cuando un contenedor flexible 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 que algo en la fila 2 se alinee con algo que está arriba en la fila 1. Esto es lo que se entiende por que flexbox es unidimensional. Puedes controlar la alineación en un eje, en una fila o en una columna, no ambos juntos como se hace en la cuadrícula.

La abreviatura de flujo flexible

Puedes configurar las propiedades flex-direction y flex-wrap con el atajo flex-flow. Por ejemplo, para establecer flex-direction en column y permitir que los elementos unan, haz lo siguiente:

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

Cómo controlar el espacio dentro de los elementos flex

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

  • flex-grow: 0: Los elementos no crecen.
  • flex-shrink: 1: Los elementos pueden reducirse más 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, mientras permites 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 en los siguientes valores:

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

El uso de flex: auto implica que los elementos tendrán diferentes tamaños, ya que el espacio que se comparte entre ellos se distribuye después de que cada elemento se diseñó 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.

Esto se descomprime en lo siguiente:

  • flex-grow: 1: Los elementos pueden tener un tamaño mayor que su flex-basis.
  • flex-shrink: 1: Los elementos pueden reducirse más que sus 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 un tamaño de cero, por lo que todo el espacio del contenedor flexible está disponible para distribuirse. Como todos los elementos tienen un factor flex-grow de 1, todos crecen de la misma manera y el espacio se comparte de forma equitativa.

Permite que los elementos crezcan a diferentes velocidades.

No es necesario que todos los elementos tengan un factor flex-grow de 1. Puedes asignar diferentes factores flex-grow a tus elementos flexibles. En la demostración a continuación, el primer elemento tiene flex: 1, el segundo flex: 2 y el tercer flex: 3. A medida que estos elementos crecen desde 0, el espacio disponible en el contenedor flexible se comparte en seis. Se le asigna 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 tercero flex-basis.

.item1 {
  flex: 1 1 auto;
}

.item2 {
  flex: 2 1 auto;
}

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

Cómo reordenar elementos flexibles

Los elementos de tu contenedor flexible se pueden reordenar con la propiedad order. Esta propiedad permite ordenar los elementos en grupos ordinales. Los elementos se organizan en la dirección que dicta flex-direction, primero los valores más bajos. Si más de un elemento tiene el mismo valor, se mostrará con los demás elementos que tengan ese valor.

En el siguiente ejemplo, se muestra este orden.

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre flexbox

El valor predeterminado de flex-direction es

row
De forma predeterminada, flexbox ajustará los elementos en una fila y los alineará al principio. Si está activado el encadenamiento, se seguirán creando filas para que fluyan los elementos secundarios.
column
Establecer flex-direction en column es una excelente manera de apilar elementos, pero no es el valor predeterminado.

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

verdadero
Se debe habilitar el enlace.
falso
Usa flex-wrap: wrap con display: flex para unir elementos secundarios

Un elemento secundario de flex parece comprimido. ¿Qué propiedad de flex ayuda a mitigar esto?

flex-grow
Esta propiedad describe si los elementos pueden crecer más allá de un tamaño de base, no cómo se deben comportar en una base.
flex-shrink
Sí, esta propiedad describe cómo controlar el tamaño si el ancho es inferior a la base.
flex-basis
Esto proporciona el punto de partida del tamaño, pero no cómo controlar situaciones de tamaño en las que el ancho es inferior al básico, como en una situación de compresión.

Descripción general de la alineación de Flexbox

Flexbox trajo consigo un conjunto de propiedades para alinear elementos y distribuir espacio entre elementos. Estas propiedades fueron tan útiles que se trasladaron a su propia especificación, y también las encontrarás en el diseño de cuadrícula. Aquí puede ver cómo funcionan cuando utiliza Flexbox.

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

  • justify-content: Es la distribución espacial en el eje principal.
  • align-content: Distribución del espacio en el eje transversal.
  • place-content: Es una abreviatura para configurar las dos propiedades anteriores.

Las propiedades que se usan para la alineación en Flexbox:

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

Si trabajas en el eje principal, las propiedades comienzan con justify-. En el eje transversal, comienzan con align-.

Cómo distribuir el espacio en el eje principal

Con el HTML que se usó anteriormente, los elementos flexibles dispuestos como una fila, hay espacio en el eje principal. Los elementos no son lo suficientemente grandes como para llenar completamente el contenedor de flex. 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 los espacios adicionales están al final.

Agrega la propiedad justify-content al contenedor flexible, asígnale un valor de flex-end y los elementos se alinearán al final del contenedor, y el espacio sobrante se colocará al principio.

.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 tu contenedor cuando trabajas como una columna, debes darle un height o block-size al contenedor. De lo contrario, no tendrás espacio adicional para distribuir.

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

Distribución del espacio entre líneas flexibles

Con un contenedor flex unido, es posible que tengas espacio para distribuir en el eje transversal. 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 de flex para cambiar ese comportamiento predeterminado.

.container {
  align-content: center;
}

Pruébalo en la demostración. El ejemplo tiene líneas ajustadas de elementos flex, 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 el primero se usa 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 */
}

Alineación de elementos en el eje cruzado

En el eje cruzado también puedes alinear tus elementos dentro de la línea flexible con 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 unidos.

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

.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 flex 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 transversal.

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 de 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 justify-self en flexbox?

Los elementos flexibles actúan como un grupo en el eje principal. Por lo tanto, no existe el concepto de dividir un elemento individual fuera 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 flex tratan los elementos como un grupo, estas propiedades no se implementan en un contexto flex.

Vale la pena saber que flexbox funciona muy bien con márgenes automáticos. Si necesitas separar un elemento de un grupo o dividirlo en dos, puedes aplicar un margen para hacerlo. En el siguiente ejemplo, 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 empuja el elemento hacia la derecha, lo que 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 tu comprensión

Pon a prueba tus conocimientos sobre flexbox

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

Para alinear verticalmente con flexbox, usa

alinear palabras clave
Genial
justifica las palabras clave
Lo sentimos
.container {
  display: flex;
  direction: ltr;
}

Para alinear horizontalmente con flexbox, usa

alinea las palabras clave
Lo sentimos
justifica las palabras clave
Genial
.container {
  display: flex;
  direction: ltr;
}

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

justify-content: flex-start
La propiedad justificar es para la alineación horizontal, no vertical.
align-content: start
content alinea las líneas flexibles, no la alineación de los elementos secundarios.
height: auto
Esto no tendrá 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, en su lugar, usa la altura del contenido.

Recursos