Comment rendre les éléments flexbox de la même taille?

187

Je veux utiliser flexbox qui a un certain nombre d'éléments qui ont tous la même largeur. J'ai remarqué que flexbox répartit l'espace de manière uniforme, plutôt que l'espace lui-même.

Par exemple:

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

Le premier élément est beaucoup plus gros que le second. Si j'ai 3 éléments, 4 éléments ou n éléments, je veux qu'ils apparaissent tous sur la même ligne avec une quantité égale d'espace par élément.

Des idées?

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

Chet
la source

Réponses:

287

Définissez-les de manière à ce que leur flex-basissoit 0(pour que tous les éléments aient le même point de départ) et permettez-leur de grandir:

flex: 1 1 0px

Votre IDE ou linter pourrait le mentionner the unit of measure 'px' is redundant. Si vous l'omettez (comme flex: 1 1 0:), IE ne le rendra pas correctement. Il pxest donc nécessaire de prendre en charge Internet Explorer, comme mentionné dans les commentaires de @fabb;

Adam
la source
65
Il convient de noter que la flexpropriété est une propriété abrégée pour les propriétés flex-grow, flex-shrinket flex-basis. Il est recommandé d'utiliser le raccourci sur les propriétés individuelles car le raccourci réinitialise correctement tous les composants non spécifiés pour s'adapter aux utilisations courantes. La valeur initiale est 0 1 auto.
j08691
3
notez que IE11 ignore les valeurs de base flex sans unité: github.com/philipwalton/flexbugs#flexbug-4
fabb
9
J'ai dû ajouter min-width: 0pour réussir à utiliser des éléments enfants avec du texte débordant. Voir css-tricks.com/flexbox-truncated-text
Iwazaru
78

Vous pourriez ajouter flex-basis: 100%pour y parvenir.

Exemple mis à jour

.header {
  display: flex;
}

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

Pour ce que ça vaut, vous pouvez également utiliser flex: 1pour les mêmes résultats.

Le raccourci de flex: 1est le même que flex: 1 1 0, ce qui équivaut à:

.item {
  flex-grow: 1;
  flex-shrink: 1;
  flex-basis: 0;
  text-align: center;
  border: 1px solid black;
}
Josh Crozier
la source
1
Ce n'est pas correct. La valeur flex par défaut est flex: 0 1 auto. Ce qui signifie que le réglage flex: 1entraînera flex: 1 1 auto. Cela ne fonctionnera pas. La bonne réponse est flex: 1 1 0comme indiqué ci-dessus par Adam
r.sendecky
17
@ r.sendecky Non, c'est vous qui avez tort. Comme je l'ai dit dans ma réponse, la sténographie des flex: 1résultats flex: 1 1 0 n'est pas flex: 1 1 auto comme vous le prétendez. Jetez un œil à la spécification officielle W3 dans la section 'flex shorthand' : quand flex-basisest "omis du raccourci flex, sa valeur spécifiée est 0", non auto. Merci pour le vote défavorable aléatoire.
Josh Crozier
2
@ r.sendecky - Jetez également un œil à cet exemple que j'ai créé pour visualiser les variations.
Josh Crozier
1
Mate, je ne vote pas au hasard. Je teste avant d'écrire. Et je l'ai testé. Votre réponse ne fonctionne pas - aussi simple que cela. J'ai eu exactement le même problème il n'y a pas longtemps avec flex: 1et flex-direction: column. La hauteur des enfants n'était pas la même lorsque d'autres éléments sont placés dans les enfants. La seule chose qui l'a corrigé était le réglage flex: 1 1 0. Il existe toujours aujourd'hui avec du chrome 55.0.2883.87
r.sendecky
4
@JoshCrozier a confirmé qu'il flex: 1a le même comportement que flex: 1 1 0et flex: 0 1 autoa un comportement différent.
Ivan Durst
66

Vous devez ajouter width: 0pour rendre les colonnes égales si le contenu des éléments l'agrandit.

.item {
  flex: 1 1 0;
  width: 0;
}
Jason Song
la source
5
Cela semble être nécessaire si le contenu du produit le .itemfait devenir plus large qu'il .itemne le serait naturellement.
Bungle
1
Je pense que vous voulez dire flex: 1 1 0;, au lieu deflex-grow: 1 1 0;
Soupe au poulet
3
Pour info, le lien est rompu
Bobby Jack
le réglage de flex-basisà a 0le même objectif que le réglage de widthà 0.
Stephen
Dans mon cas d'utilisation, j'emballais des graphiques qui s'ajustent dynamiquement à la taille de leurs parents et la largeur 0 était nécessaire pour qu'ils fonctionnent. Je ne sais pas comment ils déterminaient la largeur appropriée, mais la base flexible ne fonctionnait certainement pas sur Chrome 72 (publié en janvier 2019).
Andy Groff
12

La réponse acceptée par Adam ( flex: 1 1 0) fonctionne parfaitement pour les conteneurs flexbox dont la largeur est soit fixe, soit déterminée par un ancêtre. Situations où vous voulez que les enfants rentrent dans le conteneur.

Cependant, vous pouvez avoir une situation où vous voulez que le conteneur s'adapte aux enfants, avec les enfants de taille égale en fonction du plus grand enfant. Vous pouvez adapter un conteneur flexbox à ses enfants en:

  • réglage position: absoluteet non réglage widthou right, ou
  • placez-le dans un emballage avec display: inline-block

Pour de tels conteneurs flexbox, la réponse acceptée ne fonctionne PAS , les enfants ne sont pas de taille égale. Je présume qu'il s'agit d'une limitation de la flexbox, car elle se comporte de la même manière dans Chrome, Firefox et Safari.

La solution est d'utiliser une grille au lieu d'une flexbox.

Démo: 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
la source
0

Je ne suis pas un expert en flex mais j'y suis arrivé en définissant la base à 50% pour les deux éléments dont je m'occupais. Passez à 1 et réduisez à 0.

Style en ligne: flex: '1 0 50%',

Steve
la source