¿Cómo funciona flex-wrap con align-self, align-items y align-content?


align-self

En el siguiente código, align-self funciona con flex-wrap: nowrap.

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Pero cuando el contenedor se cambia a flex-wrap: wrap, la propiedad align-self falla.

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-items

De manera similar, ¿por qué align-items funciona aquí (wrap deshabilitado):

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

...pero no aquí (ajuste habilitado):

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

align-content

Con flex-wrap: nowrap, la propiedad align-content no centrará verticalmente los elementos flex aquí:

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Pero entonces, extrañamente, si wrap está habilitado y align-content se deja fuera, el contenedor crea amplios espacios entre filas aquí:

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Y align-self funciona nuevo.

introduzca la descripción de la imagen aquí

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

¿Cómo funciona flex-wrap con align-self, align-items y align-content?

Author: Michael_B, 2017-03-05

2 answers

Respuesta corta

Aunque la propiedad flex-wrap parece bastante básica – controla si los elementos flex pueden envolver – en realidad tiene un gran impacto en todo el diseño de flexbox.

La propiedad flex-wrap determina el tipo de contenedor flex que utilizará.

  • flex-wrap: nowrap crea un contenedor flexible de una línea
  • flex-wrap: wrap y wrap-reverse crear un flex de varias líneas contenedor

Las propiedades align-items y align-self funcionan tanto en contenedores de una línea como en contenedores de varias líneas. Sin embargo, solo pueden tener un efecto cuando hay espacio libre en el eje transversal de la línea flex.

La propiedad align-content solo funciona en contenedores multilínea. Se ignora en contenedores de una sola línea.


Explicación

La especificación flexbox proporciona cuatro propiedades de palabras clave para alinear flex items:

  • align-items
  • align-self
  • align-content
  • justify-content

Para entender las funciones de estas propiedades es importante entender primero la estructura de un contenedor flexible.


Parte 1: Comprender el Eje Principal y el Eje Transversal de un Contenedor Flexible

Los Ejes X e y

Un contenedor flexible funciona en dos direcciones: eje x (horizontal) e eje y (vertical).

eje x y eje y

Fuente: Wikipedia

Los elementos secundarios de un contenedor flex, conocidos como "elementos flex", se pueden alinear en cualquier dirección.

Esta es la alineación flex en su nivel más fundamental.

El Principal y la Cruz Ejes

La superposición de los ejes x e y son, en el diseño flexible, los ejes mainy cross.

Por defecto, el eje principal es horizontal (eje x), y el eje transversal es vertical (eje y). Esa es la configuración inicial, como se define en el flexbox especificación.

flex eje principal y eje transversal

Fuente: W3C

Sin embargo, a diferencia de los ejes x e y, que son fijos, los ejes principal y transversal pueden cambiar de dirección.

La Propiedad flex-direction

En la imagen de arriba, el eje principal es horizontal y el eje transversal es vertical. Como se mencionó anteriormente, esa es una configuración inicial de un contenedor flexible.

Sin embargo, estas direcciones se pueden cambiar fácilmente con la propiedad flex-direction. Esta propiedad controla la dirección del eje principal; determina si los elementos flex se alinean vertical u horizontalmente.

De la especificación:

5.1. Dirección de flujo flexible: el flex-direction propiedad

La propiedad flex-direction especifica cómo se colocan los elementos flex el contenedor flex, configurando la dirección del contenedor flex eje principal. Esto determina la dirección en la que se colocan los elementos flex fuera.

Hay cuatro valores para la propiedad flex-direction:

/* main axis is horizontal, cross axis is vertical */
flex-direction: row; /* default */
flex-direction: row-reverse;

/* main axis is vertical, cross axis is horizontal */    
flex-direction: column;
flex-direction: column-reverse;

El eje transversal es siempre perpendicular al eje principal.


Parte 2: Líneas flexibles

Dentro del contenedor, los elementos flex existen en una línea, conocida como "línea flex".

Una línea flexible es una fila o columna, dependiendo de flex-direction.

Un contenedor puede tener una o más líneas, dependiendo de flex-wrap.

Contenedor Flexible de Una Línea

flex-wrap: nowrap establece un contenedor flex de una sola línea, en el que los elementos flex se ven obligados a permanecer en una sola línea (incluso si desbordan el contenedor).

un contenedor flexible de una sola línea (una columna)

La imagen de arriba tiene una línea flex.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap; /* <-- allows single-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Flex de Varias Líneas Contenedor

flex-wrap: wrap o wrap-reverse establece un contenedor flex multilínea, en el que los elementos flex pueden crear nuevas líneas.

contenedor flexible multilínea (3 columnas)

La imagen de arriba tiene tres líneas flexibles.

flex-container {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  width: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

contenedor flexible multilínea (3 filas)

La imagen de arriba tiene tres líneas flexibles.

flex-container {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap; /* <-- allows multi-line flex container */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Parte 3: Alineación de palabras clave Propiedades

Las propiedades se asignan a los Ejes Principal y Transversal (no X e Y)

Mientras que la propiedad flex-direction controla la dirección en la que se presentan los elementos flex, hay cuatro propiedades que controlan la alineación y el posicionamiento. Estos son:

  • align-items
  • align-self
  • align-content
  • justify-content

Cada una de estas propiedades está asignada permanentemente a un eje.

El justify-content la propiedad funciona solo en el eje principal.

Las tres propiedades align-* funcionan solo en el eje transversal.

Es un error común asumir que estas propiedades están fijadas a los ejes x e y. Por ejemplo, justify-content es siempre horizontal, y align-items es siempre vertical.

Sin embargo, cuando flex-direction se cambia a column, el eje principal se convierte en el eje y, y justify-content funciona verticalmente.

El enfoque de este post es la alineación de ejes transversales. Para una explicación de alineación del eje principal y la propiedad justify-content, ver este post:

Definiciones

La especificación flexbox proporciona tres propiedades de palabras clave para la alineación de ejes transversales:

  • align-items
  • align-self
  • align-content

align-items / align-self

La propiedad align-items aligns flex elementos a lo largo del eje transversal de la línea flex. Se aplica a los contenedores flexibles.

La propiedad align-self se usa para anular align-items en elementos flex individuales. Se aplica a los elementos flexibles.

Aquí está la definición de la especificación:

8.3. Alineación de ejes transversales: el align-items y align-self propiedades

Los elementos flexibles se pueden alinear en el eje transversal de la línea actual del contenedor flexible, similar a justify-content pero en la perpendicular dirección. align-items establece la alineación predeterminada para todos los artículos de flex container. align-self permite esta alineación predeterminada para ser anulado para elementos flexibles individuales.

Hay seis valores posibles para align-items / align-self:

  • flex-start
  • flex-end
  • center
  • baseline
  • stretch
  • auto (align-self únicamente)

(Para una descripción de cada valor, haga clic en el encabezado definición de especificación arriba.)

El valor inicial de align-items es stretch, lo que significa que los elementos flex expandirán toda la longitud disponible del eje transversal del contenedor.

El valor inicial de align-self es auto, lo que significa que hereda el valor de align-items.

A continuación se muestra una ilustración del efecto de cada valor en una dirección de fila contenedor.

align-items align-self values

source: W3C

align-content

Esta propiedad es ligeramente más compleja que align-items y align-self.

Aquí está la definición de la especificación:

8.4. Líneas flexibles de embalaje: el align-content propiedad

La propiedad align-content alinea las líneas de un contenedor flexible dentro el contenedor flexible cuando hay espacio adicional en el eje transversal, similar a cómo justify-content alinea elementos individuales dentro de la eje principal. Tenga en cuenta que esta propiedad no tiene ningún efecto en una flexión de una sola línea contenedor.

En contraste con align-items y align-self, que mueven elementos flexibles dentro de su línea, align-content mueve las líneas flexibles dentro del contenedor.

Hay los seis valores posibles para align-content:

  • flex-start
  • flex-end
  • center
  • space-between
  • space-around
  • stretch

(Para una descripción de cada valor, haga clic en el encabezado de definición de especificaciones arriba.)

A continuación se muestra una ilustración del efecto de cada valor en una dirección de fila contenedor.

introduzca la descripción de la imagen aquí

source: W3C

¿Por qué align-content funciona solo en contenedores flex multilínea?

En un contenedor flexible de una sola línea, el tamaño de cruz de la línea es igual al tamaño de cruz del contenedor. Esto significa que no hay espacio libre entre la línea y el contenedor. Como resultado, align-content no puede tener ningún efecto.

Aquí está la sección relevante de la especificación :

Solo los contenedores flex de varias líneas tienen espacio libre en el eje transversal para que las líneas se alineen, porque en un contenedor flex de una sola línea la única línea se estira automáticamente para llenar el espacio.


Parte 4: Ejemplos explicados

introduzca la descripción de la imagen aquí

En el Ejemplo #1, align-self funciona con flex-wrap: nowrap porque los elementos flex existen en un contenedor de una sola línea. Por lo tanto, hay una línea flexible y coincide con la altura del contenedor.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

En el ejemplo #2, align-self falla porque existe en un contenedor multilínea(flex-wrap: wrap) y align-content se establece en flex-start. Esto significa que las líneas flexibles se empaquetan firmemente al comienzo del eje transversal, sin dejar espacio libre para align-self para trabajo.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

La explicación por Ejemplo #3 es la misma que por Ejemplo #1.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

La explicación por Ejemplo #4 es la misma que por Ejemplo #2.

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

El ejemplo #5 es un contenedor de una sola línea. Como tal, el tamaño de la cruz de la línea de flexión es igual a la tamaño cruzado del contenedor, sin dejar espacio adicional entre los dos. Por lo tanto, align-content, que alinea las líneas flexibles cuando hay espacio adicional en el eje transversal, no está teniendo ningún efecto.

flex-container {
  display: flex;
  flex-wrap: nowrap;
  align-content: center;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

El ajuste inicial para align-content es stretch. Esto significa que si no se especifica ningún otro valor, el contenedor distribuirá el espacio disponible de manera uniforme entre las líneas flexibles. (Se crea un efecto similar en el eje principal cuando todos los elementos flex obtienen flex: 1.)

Esta distribución del espacio entre líneas puede causar grandes espacios entre filas / columnas. Menos líneas resultan en espacios más amplios. Más líneas dan como resultado espacios más pequeños, ya que cada línea obtiene una porción más pequeña del espacio.

Para resolver este problema cambie de align-content: stretch a align-content: flex-start. Esto empaqueta las líneas juntas(ver ejemplos # 2 y #4 arriba). Por supuesto, esto también elimina cualquier espacio libre en la línea, y align-items y align-self ya no pueden trabajo.

Aquí hay un post relacionado: Eliminar el espacio (espacios) entre múltiples líneas de elementos flexibles cuando se envuelven

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

introduzca la descripción de la imagen aquí

Como se explicó en ejemplos anteriores, con align-content: stretch, puede haber espacio adicional en las líneas flexibles, lo que permite que align-items y align-self funcionen. Cualquier otro valor para align-content empaquetaría las líneas, eliminando espacio adicional, y haciendo align-items y align-self inútil.

flex-container {
  display: flex;
  flex-wrap: wrap;
  /* align-content: center; */
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}

flex-item:nth-child(even) {
  align-self: flex-end;
  background-color: crimson;
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>
 56
Author: Michael_B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:10

En primer lugar, align-content es inútil si no hay wrap:

W3c doc

La propiedad align-content alinea las líneas de un contenedor flex dentro del contenedor flex cuando hay espacio adicional en el eje transversal, de manera similar a como justify-content alinea elementos individuales dentro del eje principal. Tenga en cuenta que esta propiedad no tiene ningún efecto en un contenedor flexible de una sola línea.

Además, en su segundo caso, align-self no está fallando. Es inútil porque el las líneas interiores han sido embaladas. Vamos a crear un espacio para que el estilo pueda funcionar:

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}
flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:last-child {
  align-self: flex-end;
  background-color: crimson;
}
flex-item:nth-child(5) {
  height: 90px;  /* added */
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Del mismo modo, en su 4º ejemplo, el estilo está funcionando, si establece las condiciones donde se puede ver

flex-container {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  align-content: flex-start;
  width: 250px;
  height: 250px;
  background-color: silver;
}

flex-item {
  flex: 0 0 50px;
  height: 50px;
  margin: 5px;
  background-color: lightgreen;
}
flex-item:nth-child(2),flex-item:nth-child(5) {
  height: 90px;  /* added */
}
<flex-container>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
  <flex-item></flex-item>
</flex-container>

Finalmente, cuando comentas el align-content, vuelve a stretch , es por eso que las líneas aumentan el tamaño para llenar el contenedor

Estirar Las líneas se extienden para ocupar el espacio restante. Si el espacio libre sobrante es negativo, este valor es idéntico a flex-start. De lo contrario, el espacio libre se divide por igual entre todas las líneas, aumentando su tamaño de cruz.

 3
Author: vals,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-05 21:22:36