¿Cómo hacer que los artículos flexbox sean del mismo tamaño?

186

Quiero usar flexbox que tiene una cierta cantidad de elementos que son todos del mismo ancho. Me di cuenta de que flexbox distribuye el espacio de manera uniforme, en lugar del espacio en sí.

Por ejemplo:

.header {
  display: flex;
}

.item {
  flex-grow: 1;
  text-align: center;
  border: 1px solid black;
}
<div class="header">
  <div class="item">asdfasdfasdfasdfasdfasdf</div>
  <div class="item">z</div>
</div>

El primer artículo es mucho más grande que el segundo. Si tengo 3 elementos, 4 elementos o n elementos, quiero que todos aparezcan en la misma línea con la misma cantidad de espacio por elemento.

¿Algunas ideas?

http://codepen.io/anon/pen/gbJBqM

Chet
fuente

Respuestas:

287

Configurarlos para que su flex-basises 0(por lo que todos los elementos tienen el mismo punto de partida), y les permiten crecer:

flex: 1 1 0px

Su IDE o linter podría mencionar eso the unit of measure 'px' is redundant. Si lo deja fuera (como flex: 1 1 0:), IE no lo procesará correctamente. Por lo tanto, pxes necesario para admitir Internet Explorer, como se menciona en los comentarios de @fabb;

Adán
fuente
65
Debe tenerse en cuenta que la flexpropiedad es una propiedad abreviada para los flex-grow, flex-shrinky flex-basispropiedades. Se recomienda usar la taquigrafía sobre las propiedades individuales ya que la taquigrafía restablece correctamente cualquier componente no especificado para acomodar usos comunes. El valor inicial es 0 1 auto.
j08691
3
tenga en cuenta que IE11 ignora los valores de base flexible sin unidades: github.com/philipwalton/flexbugs#flexbug-4
fabb
9
Tuve que agregar min-width: 0para lograr el uso de elementos secundarios con texto desbordado. Ver css-tricks.com/flexbox-truncated-text
Iwazaru
77

Podrías agregar flex-basis: 100%para lograr esto.

Ejemplo actualizado

.header {
  display: flex;
}

.item {
  flex-basis: 100%;
  text-align: center;
  border: 1px solid black;
}

Por lo que vale, también podría usarlo flex: 1para obtener los mismos resultados.

La abreviatura de flex: 1es la misma que flex: 1 1 0, que es equivalente a:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  text-align: center;
  border: 1px solid black;
}
Josh Crozier
fuente
1
Esto no es correcto. El valor flex predeterminado es flex: 0 1 auto. Lo que significa que la configuración flex: 1dará como resultado flex: 1 1 auto. Esto no funcionará. La respuesta correcta es la flex: 1 1 0indicada anteriormente por Adam
r.sendecky
17
@ r.sendecky No, usted es el incorrecto. Como dije en mi respuesta, la taquigrafía de los flex: 1resultados flex: 1 1 0 no es flex: 1 1 auto como la que estás reclamando. Eche un vistazo a la especificación oficial de W3 en la sección 'taquigrafía flexible' : cuando flex-basisse "omite de la taquigrafía flexible, su valor especificado es 0", no auto. Gracias por el voto negativo al azar.
Josh Crozier
2
@ r.sendecky - Además, eche un vistazo a este ejemplo que creé para visualizar las variaciones.
Josh Crozier
1
Compañero, no hago votos al azar. Pruebo antes de escribir. Y lo probé. Su respuesta no funciona, así de simple. Tuve exactamente el mismo problema no hace mucho con flex: 1y flex-direction: column. La altura de los niños no era la misma cuando se colocaban otros elementos dentro de los niños. Lo único que lo solucionó fue la configuración flex: 1 1 0. Todavía se mantiene hoy con cromo 55.0.2883.87
r.sendecky
44
@JoshCrozier confirmó que flex: 1tiene el mismo comportamiento flex: 1 1 0y flex: 0 1 autotiene un comportamiento diferente.
Ivan Durst
66

Debe agregar width: 0para hacer que las columnas sean iguales si el contenido de los elementos lo hace crecer más grande.

.item {
  flex: 1 1 0;
  width: 0;
}
Jason Song
fuente
55
Esto parece ser necesario si el contenido de .itemhace que crezca más de .itemlo que sería naturalmente.
Bungle
1
Creo que te refieres a flex: 1 1 0;, en lugar deflex-grow: 1 1 0;
Sopa de pollo
3
digo, el enlace está roto
Bobby Jack
configurar flex-basisto 0sirve para el mismo propósito que configurar widthto 0.
Stephen
En mi caso de uso, estaba envolviendo gráficos que se ajustaban dinámicamente al tamaño de sus padres y el ancho 0 era necesario para que funcionen. No estoy seguro de cómo estaban determinando el ancho adecuado, pero la base flexible ciertamente no funcionó en Chrome 72 (lanzado en enero de 2019).
Andy Groff
12

La respuesta aceptada por Adam (flex: 1 1 0 ) funciona perfectamente para contenedores flexbox cuyo ancho es fijo o determinado por un antepasado. Situaciones en las que desea que los niños encajen en el contenedor.

Sin embargo, puede tener una situación en la que desea que el contenedor se ajuste a los niños, con los niños del mismo tamaño en función del niño más grande. Puede hacer que un contenedor flexbox se ajuste a sus hijos de la siguiente manera:

  • ajuste position: absolutey no ajuste widtho right, o
  • colóquelo dentro de una envoltura con display: inline-block

Para tales contenedores flexbox, la respuesta aceptada NO funciona, los niños no tienen el mismo tamaño. Supongo que esta es una limitación de flexbox, ya que se comporta igual en Chrome, Firefox y Safari.

La solución es usar una cuadrícula en lugar de una caja flexible.

Demostración: https://codepen.io/brettdonald/pen/oRpORG

<p>Normal scenario — flexbox where the children adjust to fit the container — and the children are made equal size by setting {flex: 1 1 0}</p>

<div id="div0">
  <div>
    Flexbox
  </div>
  <div>
    Width determined by viewport
  </div>
  <div>
    All child elements are equal size with {flex: 1 1 0}
  </div>
</div>

<p>Now we want to have the container fit the children, but still have the children all equally sized, based on the largest child. We can see that {flex: 1 1 0} has no effect.</p>

<div class="wrap-inline-block">
<div id="div1">
  <div>
    Flexbox
  </div>
  <div>
    Inside inline-block
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
</div>

<div id="div2">
  <div>
    Flexbox
  </div>
  <div>
    Absolutely positioned
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>

<br><br><br><br><br><br>
<p>So let's try a grid instead. Aha! That's what we want!</p>

<div class="wrap-inline-block">
<div id="div3">
  <div>
    Grid
  </div>
  <div>
    Inside inline-block
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
</div>

<div id="div4">
  <div>
    Grid
  </div>
  <div>
    Absolutely positioned
  </div>
  <div>
    We want all children to be the size of this text
  </div>
</div>
body {
  margin: 1em;
}

.wrap-inline-block {
  display: inline-block;
}

#div0, #div1, #div2, #div3, #div4 {
  border: 1px solid #888;
  padding: 0.5em;
  text-align: center;
  white-space: nowrap;
}

#div2, #div4 {
  position: absolute;
  left: 1em;
}

#div0>*, #div1>*, #div2>*, #div3>*, #div4>* {
  margin: 0.5em;
  color: white;
  background-color: navy;
  padding: 0.5em;
}

#div0, #div1, #div2 {
  display: flex;
}

#div0>*, #div1>*, #div2>* {
  flex: 1 1 0;
}

#div0 {
  margin-bottom: 1em;
}

#div2 {
  top: 15.5em;
}

#div3, #div4 {
  display: grid;
  grid-template-columns: repeat(3,1fr);
}

#div4 {
  top: 28.5em;
}
Brett Donald
fuente
0

No soy un experto en flex, pero llegué estableciendo la base al 50% para los dos elementos con los que estaba tratando. Crecer a 1 y reducir a 0.

Estilo en línea: flex: '1 0 50%',

Steve
fuente