En CSS Flexbox, ¿por qué no hay propiedades "justify-items" y "justify-self"?

678

Considere el eje principal y el eje transversal de un contenedor flexible:

ingrese la descripción de la imagen aquí                                                                                                                                                    Fuente: W3C

Para alinear elementos flexibles a lo largo del eje principal hay una propiedad:

Para alinear elementos flexibles a lo largo del eje transversal, hay tres propiedades:

En la imagen de arriba, el eje principal es horizontal y el eje transversal es vertical. Estas son las direcciones predeterminadas de un contenedor flexible.

Sin embargo, estas direcciones pueden intercambiarse fácilmente con la flex-directionpropiedad.

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

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

(El eje transversal siempre es perpendicular al eje principal).

Mi punto al describir cómo funcionan los ejes es que no parece haber nada especial en ninguna dirección. Eje principal, eje transversal, ambos son iguales en términos de importancia y flex-directionhace que sea fácil cambiar de un lado a otro.

Entonces, ¿por qué el eje transversal obtiene dos propiedades de alineación adicionales?

¿Por qué son align-contenty align-itemsconsolidado en una propiedad para el eje principal?

¿Por qué el eje principal no obtiene una justify-selfpropiedad?


Escenarios donde estas propiedades serían útiles:

  • colocando un elemento flexible en la esquina del contenedor flexible
    #box3 { align-self: flex-end; justify-self: flex-end; }

  • hacer que un grupo de elementos flexibles se alinee a la derecha ( justify-content: flex-end) pero que el primer elemento se alinee a la izquierda ( justify-self: flex-start)

    Considere una sección de encabezado con un grupo de elementos de navegación y un logotipo. Con justify-selfel logotipo podría alinearse a la izquierda, mientras que los elementos de navegación permanecen muy a la derecha, y todo se ajusta sin problemas ("flexiona") a diferentes tamaños de pantalla.

  • en una fila de tres elementos flexibles, fije el elemento central al centro del contenedor ( justify-content: center) y alinee los elementos adyacentes a los bordes del contenedor ( justify-self: flex-starty justify-self: flex-end).

    Tenga en cuenta que los valores space-aroundy space-betweenen la justify-contentpropiedad no mantendrán el elemento central centrado sobre el contenedor si los elementos adyacentes tienen anchuras diferentes.

Versión jsFiddle


Al momento de escribir esto, no hay mención de justify-selfo justify-itemsen la especificación de flexbox .

Sin embargo, en el Módulo de alineación de cajas CSS , que es la propuesta inacabada del W3C para establecer un conjunto común de propiedades de alineación para su uso en todos los modelos de cajas, existe esto:

ingrese la descripción de la imagen aquí                                                                                                                                                    Fuente: W3C

Notarás eso justify-selfy justify-itemsestás siendo considerado ... pero no para flexbox .


Terminaré reiterando la pregunta principal:

¿Por qué no hay propiedades "justify-items" y "justify-self"?

Michael Benjamin
fuente
44
¿Cómo esperarías justify-selftrabajar para un artículo flexible? Supongamos que tiene elementos a, b, c, d con espacio adicional para distribuir a su alrededor, y el contenedor flexible tiene justify-content: space-between, por lo que terminan como | abcd |. ¿Qué significaría agregar, por ejemplo, justify-self: centero 'justify-self: flex-end' solo al elemento 'b' allí? ¿Dónde esperarías que fuera? (Veo algunas demostraciones en una de las respuestas aquí, pero no veo una forma clara de que funcione en general.)
dholbert
(Alternativamente: supongamos que sí justify-content: flex-start, así que los artículos están llenos al principio como | abcd |. ¿Qué esperarías que hiciera si justify-self: [anything]
pusieras
1
@dholbert, usted escribió: ¿Cómo esperaría justify-selftrabajar para un artículo flexible? Yo diría que no de manera diferente a los automárgenes que ya funcionan en artículos flexibles. En su segundo ejemplo, justify-self: flex-enden el elemento d lo movería al borde lejano. Eso en sí mismo sería una gran característica, que los automárgenes ya pueden hacer. Publiqué una respuesta con una demostración.
Michael Benjamin
2
La mayoría de las veces veo más casos de uso aquí, y los casos de uso son geniales, pero la parte difícil es cómo calzar esto en la forma realjustify-content y justify-selfespecífica, de modo que los casos con conflictos (como los escenarios que pregunté) están definidos de manera clara y sensata. Como señalé en mi respuesta aquí, {justify|align}-selfse trata de alinear elementos dentro de un cuadro más grande que tiene un tamaño independiente del {justify|align}-selfvalor , y no existe dicho cuadro, en el eje principal, para alinear un elemento flexible.
dholbert
1
RE "no es diferente de los márgenes automáticos": en realidad estaba preguntando cómo te imaginas justify-selfe justify-contentinteractuarías, en los casos en que entran en conflicto (como los escenarios que expuse). Los márgenes automáticos simplemente no interactúan justify-contenten absoluto: roban todo el espacio de empaque antes de tener la justify-contentoportunidad de usarlo. Entonces, los márgenes automáticos no son realmente un buen análogo de cómo funcionaría esto.
dholbert

Respuestas:

1255

Métodos para alinear elementos flexibles a lo largo del eje principal

Como se indica en la pregunta:

Para alinear elementos flexibles a lo largo del eje principal hay una propiedad: justify-content

Para artículos de flexión alinean a lo largo del eje transversal hay tres propiedades: align-content, align-itemsyalign-self .

La pregunta luego pregunta:

¿Por qué no hay justify-itemsy justify-selfpropiedades?

Una respuesta puede ser: porque no son necesarios.

La especificación flexbox proporciona dos métodos para alinear elementos flexibles a lo largo del eje principal:

  1. La justify-contentpropiedad de palabra clave y
  2. auto márgenes

justificar-contenido

La justify-contentpropiedad alinea los elementos flexibles a lo largo del eje principal del contenedor flexible.

Se aplica al contenedor flexible pero solo afecta a los artículos flexibles.

Hay cinco opciones de alineación:

  • flex-start ~ Los artículos flexibles se empaquetan hacia el inicio de la línea.

    ingrese la descripción de la imagen aquí

  • flex-end ~ Los artículos flexibles se empaquetan hacia el final de la línea.

    ingrese la descripción de la imagen aquí

  • center ~ Los artículos flexibles se empaquetan hacia el centro de la línea.

    ingrese la descripción de la imagen aquí

  • space-between~ Los artículos flexibles están espaciados uniformemente, con el primer artículo alineado a un borde del contenedor y el último artículo alineado al borde opuesto. Los bordes utilizados por los primeros y últimos artículos depende de flex-directiony modo de escritura ( ltro rtl).

    ingrese la descripción de la imagen aquí

  • space-around~ Igual que space-betweenexcepto con espacios de tamaño medio en ambos extremos.

    ingrese la descripción de la imagen aquí


Márgenes automáticos

Con los automárgenes , los elementos flexibles pueden centrarse, separarse o agruparse en subgrupos.

A diferencia de lo justify-contentque se aplica al contenedor flexible, los automárgenes se aplican a los elementos flexibles.

Funcionan consumiendo todo el espacio libre en la dirección especificada.


Alinee el grupo de elementos flexibles a la derecha, pero el primer elemento a la izquierda.

Escenario de la pregunta:

  • hacer que un grupo de elementos flexibles se alinee a la derecha ( justify-content: flex-end) pero que el primer elemento se alinee a la izquierda ( justify-self: flex-start)

    Considere una sección de encabezado con un grupo de elementos de navegación y un logotipo. Con justify-selfel logotipo podría alinearse a la izquierda, mientras que los elementos de navegación permanecen muy a la derecha, y todo se ajusta sin problemas ("flexiona") a diferentes tamaños de pantalla.

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí


Otros escenarios útiles:

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí


Coloque un elemento flexible en la esquina

Escenario de la pregunta:

  • colocando un elemento flexible en una esquina .box { align-self: flex-end; justify-self: flex-end; }

ingrese la descripción de la imagen aquí


Centre un elemento flexible vertical y horizontalmente

ingrese la descripción de la imagen aquí

margin: autoes una alternativa a justify-content: centery align-items: center.

En lugar de este código en el contenedor flexible:

.container {
    justify-content: center;
    align-items: center;
}

Puede usar esto en el elemento flexible:

.box56 {
    margin: auto;
}

Esta alternativa es útil cuando se centra un elemento flexible que desborda el contenedor .


Centre un elemento flexible y centre un segundo elemento flexible entre el primero y el borde

Un contenedor flexible alinea los artículos flexibles mediante la distribución de espacio libre.

Por lo tanto, para crear un equilibrio igual , de modo que un elemento intermedio pueda centrarse en el contenedor con un único elemento al lado, debe introducirse un contrapeso.

En los ejemplos a continuación, se introducen los terceros elementos flexibles invisibles (recuadros 61 y 68) para equilibrar los elementos "reales" (recuadros 63 y 66).

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí

Por supuesto, este método no es nada bueno en términos de semántica.

Alternativamente, puede usar un pseudo-elemento en lugar de un elemento DOM real. O puede usar el posicionamiento absoluto. Aquí se cubren los tres métodos: elementos flexibles centrales y de alineación inferior

NOTA: Los ejemplos anteriores solo funcionarán, en términos de centrado verdadero, cuando los elementos más externos tengan la misma altura / anchura. Cuando los artículos flexibles tienen diferentes longitudes, vea el siguiente ejemplo.


Centre un elemento flexible cuando los elementos adyacentes varían de tamaño

Escenario de la pregunta:

  • en una fila de tres elementos flexibles, fije el elemento central al centro del contenedor ( justify-content: center) y alinee los elementos adyacentes a los bordes del contenedor ( justify-self: flex-starty justify-self: flex-end).

    Tenga en cuenta que los valores space-aroundy space-betweenen la justify-contentpropiedad no mantendrán el elemento central centrado en relación con el contenedor si los elementos adyacentes tienen anchuras diferentes ( vea la demostración ).

Como se señaló, a menos que todos los elementos flexibles sean del mismo ancho o alto (dependiendo de flex-direction), el elemento central no puede estar verdaderamente centrado. Este problema es un buen argumento para una justify-selfpropiedad (diseñada para manejar la tarea, por supuesto).

Aquí hay dos métodos para resolver este problema:

Solución # 1: Posicionamiento absoluto

La especificación flexbox permite el posicionamiento absoluto de los elementos flexibles . Esto permite que el elemento central esté perfectamente centrado, independientemente del tamaño de sus hermanos.

Solo tenga en cuenta que, como todos los elementos posicionados absolutamente, los elementos se eliminan del flujo de documentos . Esto significa que no ocupan espacio en el contenedor y pueden superponerse a sus hermanos.

En los ejemplos a continuación, el elemento central se centra con un posicionamiento absoluto y los elementos externos permanecen en flujo. Pero se puede lograr el mismo diseño de manera inversa: centrar el elemento central con justify-content: centery posicionar absolutamente los elementos externos.

ingrese la descripción de la imagen aquí

Solución n. ° 2: Contenedores flexibles anidados (sin posicionamiento absoluto)

.container {
  display: flex;
}
.box {
  flex: 1;
  display: flex;
  justify-content: center;
}
.box71 > span { margin-right: auto; }
.box73 > span { margin-left: auto;  }

/* non-essential */
.box {
  align-items: center;
  border: 1px solid #ccc;
  background-color: lightgreen;
  height: 40px;
}
<div class="container">
  <div class="box box71"><span>71 short</span></div>
  <div class="box box72"><span>72 centered</span></div>
  <div class="box box73"><span>73 loooooooooooooooong</span></div>
</div>

Así es como funciona:

  • El div ( .container) de nivel superior es un contenedor flexible.
  • Cada elemento div ( .box) ahora es un elemento flexible.
  • Cada .boxartículo se entrega flex: 1para distribuir el espacio del contenedor por igual.
  • Ahora los artículos están consumiendo todo el espacio en la fila y tienen el mismo ancho.
  • Convierta cada elemento en un contenedor flexible (anidado) y agregue justify-content: center.
  • Ahora cada spanelemento es un elemento flexible centrado.
  • Use automárgenes flexibles para desplazar el exterior hacia spanla izquierda y hacia la derecha.

También puede renunciar justify-contenty usar automárgenes exclusivamente.

Pero justify-contentpuede funcionar aquí porque los automárgenes siempre tienen prioridad. De la especificación:

8.1. Alineándose con auto márgenes

Antes de la alineación a través de justify-contenty align-self, cualquier espacio libre positivo se distribuye a los márgenes automáticos en esa dimensión.


justify-content: space-same (concepto)

Volviendo a justify-contentpor un minuto, aquí hay una idea para una opción más.

  • space-same~ Un híbrido de space-betweeny space-around. Los elementos flexibles están espaciados uniformemente (como space-between), excepto que en lugar de espacios de tamaño medio en ambos extremos (como space-around), hay espacios de tamaño completo en ambos extremos.

Este diseño se puede lograr con ::beforey ::afterpseudo-elementos en el contenedor flexible.

ingrese la descripción de la imagen aquí

(crédito: @oriol para el código y @crl para la etiqueta)

ACTUALIZACIÓN: Los navegadores han comenzado a implementar space-evenly, lo que cumple con lo anterior. Vea esta publicación para más detalles: igual espacio entre elementos flexibles


PATIO (incluye código para todos los ejemplos anteriores)

Michael Benjamin
fuente
1
La respuesta anterior cubre el eje principal , justify-contenty automárgenes. Por la otra cara de la moneda - el eje transversal , align-items, align-selfy align-content- véase este post: stackoverflow.com/q/42613359/3597276
Michael Benjamin
44
@ MarkW, usted está defendiendo la justify-selfpropiedad ... los automárgenes son útiles, pero justify-self: centerserían ideales. La forma de resolver el problema que presentó sería crear elementos duplicados invisibles en el lado opuesto. Vea mi respuesta aquí: stackoverflow.com/q/38948102/3597276
Michael Benjamin
55
Tu space-sameconcepto es algo real ahora. Se llama space-evenly, pero solo es compatible con Firefox en este momento: developer.mozilla.org/en-US/docs/Web/CSS/justify-content
benface
1
@benface, sí, tienes razón. Gracias por señalar eso. De hecho, he estado escribiendo space-evenlyen otras respuestas: stackoverflow.com/q/45134400/3597276
Michael Benjamin
1
De hecho, space-evenly fue compatible con Chrome 57-60, pero solo para el diseño de cuadrícula. Fue un error que se ha solucionado, y desde Chrome 61 también es compatible con Flexbox. Además, no es la forma de emular sin pseudo-elementos: .item { margin-right: auto } .item:first-child { margin-left: auto }.
Ilya Streltsyn
155

Sé que esto no es una respuesta, pero me gustaría contribuir a este asunto por lo que vale. Sería genial si pudieran lanzar justify-selfFlexbox para que sea realmente flexible.

Creo que cuando hay varios elementos en el eje, la forma más lógica de justify-selfcomportarse es alinearse con sus vecinos más cercanos (o borde) como se muestra a continuación.

Realmente espero que el W3C se dé cuenta de esto y al menos lo considere. =)

ingrese la descripción de la imagen aquí

De esta manera, puede tener un elemento que esté realmente centrado, independientemente del tamaño del cuadro izquierdo y derecho. Cuando una de las cajas alcanza el punto de la caja central, simplemente la empujará hasta que no haya más espacio para distribuir.

ingrese la descripción de la imagen aquí

La facilidad para crear diseños increíbles es infinita, eche un vistazo a este ejemplo "complejo".

ingrese la descripción de la imagen aquí

marca
fuente
12
@ Mark, ¡esto es increíble! Gracias por tomarse el tiempo para redactar esto. Espero que no te
importe,
1
@Zaqx seguro, cuanta más exposición, mejor. Espero sinceramente que encuentren una manera de hacer realidad esta realidad, me encantaría ensuciarme las manos con esto.
Mark
1
Hola Mark, @Zaqx, publiqué una respuesta que puede cubrir algunos de los casos de uso mencionados en esta respuesta. He descubierto que todavía se puede hacer mucho en el eje principal sin necesidad de justify-selfy justify-items.
Michael Benjamin
3
@Michael_B Me alegra que hayas aprendido más sobre flexbox y aprecio que te tomaste el tiempo para dar formato a tus notas en una respuesta. Margen: auto es realmente genial (aunque encontrará que los navegadores que implementaron las versiones 2009 y 2012 de la especificación flexbox no tienen una característica equivalente que reduzca drásticamente la capacidad de usarla en un sitio de producción). Sin embargo, incluso con los navegadores que admiten margen: automático, el caso de uso principal aquí de un elemento que está centrado en relación con su contenedor mientras exista espacio sigue siendo imposible sin una propiedad justify-self o similar.
Zaqx
1
@Zaqx, gracias por los comentarios. Y sí, estoy de acuerdo con usted, los automárgenes no son un sustituto completo de justify-self. Tuve cuidado de redactar mi comentario anterior diciendo que los automárgenes cubrirán algunos de los casos de uso . Como notó, no puede centrar un elemento en su lugar cuando los elementos adyacentes son de diferentes tamaños. Sin embargo, proporciona más opciones para alinear elementos flexibles. Cuando comencé a aprender sobre Flexbox, pensé que los justify-contentelementos espaciadores invisibles eran la única forma.
Michael Benjamin
20

Esto se preguntó en la lista de estilo www, y Tab Atkins (editor de especificaciones) proporcionó una respuesta explicando por qué . Lo explicaré un poco aquí.

Para comenzar, supongamos inicialmente que nuestro contenedor flexible es de una sola línea ( flex-wrap: nowrap). En este caso, hay claramente una diferencia de alineación entre el eje principal y el eje transversal: hay varios elementos apilados en el eje principal, pero solo un elemento apilado en el eje transversal. Por lo tanto, tiene sentido tener un "align-self" personalizable por elemento en el eje transversal (ya que cada elemento está alineado por separado, por sí solo), mientras que no tiene sentido en el eje principal (ya que allí, el los artículos están alineados colectivamente).

Para flexbox multilínea, la misma lógica se aplica a cada "línea flexible". En una línea determinada, los elementos se alinean individualmente en el eje transversal (ya que solo hay un elemento por línea, en el eje transversal), en comparación con el eje principal.


Aquí hay otra forma de expresarlo: por lo tanto, todas las propiedades *-selfy *-contentse refieren a cómo distribuir espacio adicional alrededor de las cosas. Pero la diferencia clave es que las *-selfversiones son para casos en los que solo hay una cosa en ese eje , y las *-contentversiones son para cuando potencialmente hay muchas cosas en ese eje . Los escenarios de una cosa versus muchas cosas son diferentes tipos de problemas, por lo que tienen diferentes tipos de opciones disponibles, por ejemplo, los valores space-around/ space-betweentienen sentido para *-content, pero no para *-self.

SO: En el eje principal de un flexbox, hay muchas cosas para distribuir el espacio. Entonces, una *-contentpropiedad tiene sentido allí, pero no una *-selfpropiedad.

Por el contrario, en el eje transversal, tenemos *-selfuna *-contentpropiedad a y una . Uno determina cómo distribuiremos el espacio alrededor de las muchas líneas flexibles ( align-content), mientras que el otro ( align-self) determina cómo distribuir el espacio alrededor de elementos flexibles individuales en el eje transversal, dentro de una línea flexible dada.

(Estoy ignorando las *-itemspropiedades aquí, ya que simplemente establecen valores predeterminados para *-self).

dholbert
fuente
1
Entiendo cómo a justify-selfpodría ser un problema en un eje con varios elementos en lugar de un elemento. Sin embargo, realmente espero que lo analicen más a fondo, en una situación de varios elementos, cómo se justify-selfcomportaría, porque hay algunas situaciones en las que esto podría ser realmente útil. Por ejemplo ( stackoverflow.com/questions/32378953/… ).
Mark
Buen hallazgo en esa lista de correo. Tratando de entenderlo, ya que todavía veo buenas posibilidades de uso justify-self.
Michael Benjamin
Agregué un poco más de aclaración, explicando cómo *-selfse trata de casos en los que solo tenemos una cosa para alinear, mientras que *-contentse trata de casos en los que tenemos muchas cosas para alinear. ¿Eso lo hace un poco más claro?
dholbert
Sí, está más claro. Agradezco la explicación. Pero parece que todo se reduce a una simple preferencia por los autores de las especificaciones, no a una necesidad particular basada en la lógica. De la lista de correo a la que hizo referencia : las propiedades * -self solo funcionan si el elemento secundario está solo en ese eje. ¿Por qué? No parece ser necesario para esto. Es una decisión arbitraria. Una preferencia. De hecho, los automárgenes, que también son parte de la especificación, permiten la alineación * con varios elementos en la línea. No hay una razón clara por la que las propiedades de palabras clave no puedan, también.
Michael Benjamin
1

Sé que esto no usa flexbox, pero para el caso de uso simple de tres elementos (uno a la izquierda, uno en el centro, uno a la derecha), esto se puede lograr fácilmente usando display: gridlos padres, grid-area: 1/1/1/1;los niños y el justify-selfposicionamiento de esos niños

<div style="border: 1px solid red; display: grid; width: 100px; height: 25px;">
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: left;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: center;"></div>
  <div style="border: 1px solid blue; width: 25px; grid-area: 1/1/1/1; justify-self: right;"></div>
</div>

Venryx
fuente
Gracias por la respuesta, pero en realidad no aborda la pregunta. Además, hay una manera más simple de lograr su diseño: jsfiddle.net/fga89m2o
Michael Benjamin
0

Acabo de encontrar mi propia solución a este problema, o al menos mi problema.
Estaba usando en justify-content: space-aroundlugar de justify-content: space-between;.

De esta manera, los elementos finales se adherirán a la parte superior e inferior, y podría tener márgenes personalizados si lo desea.

Leif Messinger LOAF
fuente