Rangées de hauteur égale dans un conteneur flexible

91

Comme vous pouvez le voir, list-itemsles premiers rowont la même chose height. Mais les éléments du second rowsont différents heights. Je veux que tous les articles aient un uniforme height.

Existe-t-il un moyen d'y parvenir sans donner une hauteur fixe et en n'utilisant que flexbox ?

entrez la description de l'image ici

Voici mon code

.list {
  display: flex;
  flex-wrap: wrap;
  max-width: 500px;
}
.list-item {
  background-color: #ccc;
  display: flex;
  padding: 0.5em;
  width: 25%;
  margin-right: 1%;
  margin-bottom: 20px;
}
.list-content {
  width: 100%;
}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
      <h2>box 1</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>
</ul>

Jinu Kurian
la source
Une façon est de régler la hauteur de l'élément qui peut varier en hauteur
onmyway133

Réponses:

79

La réponse est non.

La raison est fournie dans la spécification de la flexbox:

6. Lignes flexibles

Dans un conteneur flexible multiligne, la taille transversale de chaque ligne est la taille minimale nécessaire pour contenir les éléments flexibles sur la ligne.

En d'autres termes, lorsqu'il y a plusieurs lignes dans un conteneur flexible basé sur des lignes, la hauteur de chaque ligne (la «taille croisée») est la hauteur minimale nécessaire pour contenir les éléments flexibles sur la ligne.

Cependant, des lignes de hauteur égale sont possibles dans CSS Grid Layout:

Sinon, envisagez une alternative JavaScript.

Michael Benjamin
la source
La grille CSS est-elle sûre à utiliser comme pour le moment?
Alexander Kim
40

Vous pouvez accomplir cela maintenant avec display: grid:

.list {
  display: grid;
  overflow: hidden;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
  grid-column-gap: 5px;
  grid-row-gap: 5px;
  max-width: 500px;
}
.list-item {
  background-color: #ccc;
  display: flex;
  padding: 0.5em;
  margin-bottom: 20px;
}
.list-content {
  width: 100%;
}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
      <h2>box 1</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>
</ul>

Bien que la grille elle-même ne soit pas une flexbox, elle se comporte de manière très similaire à un conteneur flexbox , et les éléments à l'intérieur de la grille peuvent être flexibles .

La disposition de la grille est également très pratique dans le cas où vous souhaitez des grilles réactives. Autrement dit, si vous souhaitez que la grille ait un nombre différent de colonnes par ligne, vous pouvez simplement changer grid-template-columns:

grid-template-columns: repeat(1, 1fr); // 1 column
grid-template-columns: repeat(2, 1fr); // 2 columns
grid-template-columns: repeat(3, 1fr); // 3 columns

etc...

Vous pouvez le mélanger avec des requêtes multimédias et le modifier en fonction de la taille de la page.

Malheureusement, il n'y a toujours pas de support pour les requêtes de conteneur / requêtes d'élément dans les navigateurs (prêtes à l'emploi) pour que cela fonctionne bien en modifiant le nombre de colonnes en fonction de la taille du conteneur, pas de la taille de la page (ce serait génial à utiliser avec des composants Web réutilisables).

Plus d'informations sur la disposition de la grille:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

Prise en charge de la disposition en grille dans les navigateurs:

https://caniuse.com/#feat=css-grid

Lucas Basquerotto
la source
C'est le genre d'approche «can do» que j'aime! Merci pour l'exemple de travail également
hananamar
0

Si vous connaissez les éléments que vous mappez, vous pouvez accomplir cela en effectuant une ligne à la fois . Je sais que c'est une solution de contournement, mais cela fonctionne.

Pour moi, j'avais 4 articles par rangée, donc je l'ai divisé en deux rangées de 4 avec chaque rangée height: 50%, débarrassez-vous flex-grow, ayez <RowOne />et <RowTwo />en un <div>avec flex-column. Ça fera l'affaire

<div class='flexbox flex-column height-100-percent'>
   <RowOne class='flex height-50-percent' />
   <RowTwo class='flex height-50-percent' />
</div>
Kevin Danikowski
la source
0

Cela semble fonctionner dans les cas avec une hauteur de parent fixe (testée dans Chrome et Firefox):

.child {
        height    : 100%;
        overflow  : hidden;
}

.parent {
        display: flex;
        flex-direction: column;
        height: 70vh; // ! won't work unless parent container height is set
        position: relative;
}

S'il n'est pas possible d'utiliser des grilles pour une raison quelconque, c'est peut-être la solution.

Stanislav E. Govorov
la source
0

En ce qui concerne la solution alternative interactive mentionnée dans la première réponse ... Forcer les colonnes flex à avoir la même hauteur dans toutes les lignes peut être fait en utilisant jQuery lors du chargement:

$(function () {
    // Set the cards height to be the same in all lines
    $('.same-wrap-height').each(function () {
        let heighest = 0;

        $('.new-card', this).each(function () {
            if ($(this).height() > heighest) {
                heighest = $(this).height();
            }
        });

        $('.new-card', this).height(heighest);
    });
});

Ma disposition Bootstrap:

<div class="row same-wrap-height">
    <div class="col-lg-6 ... new-card">
        <div class="card h-100">
            ...
        </div>
    </div>

    <div class="col-lg-6 ... new-card">
        <div class="card h-100">
            ...
        </div>
    </div>
</div>
Sky7ure
la source
-1

Dans votre cas, la hauteur sera calculée automatiquement, vous devez donc fournir la hauteur à
utiliser

.list-content{
  width: 100%;
  height:150px;
}
À M
la source
Je suis désolé, la hauteur peut varier avec le contenu. Donc, je ne peux pas donner une hauteur fixe.
Jinu Kurian
Les hauteurs sont calculées automatiquement, donc avec votre contenu différent, les hauteurs seront différentes, vous devez donc utiliser une hauteur fixe, sinon vous ne pouvez pas obtenir des hauteurs uniformes.
Tom
-1

Vous pouvez avec flexbox:

ul.list {
    padding: 0;
    list-style: none;
    display: flex;
    align-items: stretch;
    justify-items: center;
    flex-wrap: wrap;
    justify-content: center;
}
li {
    width: 100px;
    padding: .5rem;
    border-radius: 1rem;
    background: yellow;
    margin: 0 5px;
}
<ul class="list">
  <li>title 1</li>
  <li>title 2<br>new line</li>
  <li>title 3<br>new<br>line</li>
</ul>

Hisham Dalal
la source
Je ne pense pas que cela donne une hauteur égale lorsque les éléments sont empilés verticalement.
workwise il y a
désolé, mais vous pouvez essayer une autre réponse au lieu de marquer ma réponse négative!
Hisham Dalal il y a
-3

vous pouvez le faire en fixant la hauteur de la balise "P" ou en fixant la hauteur de "list-item".

Je l'ai fait en fixant la hauteur de "P"

et le débordement doit être masqué.

.list{
  display: flex;
  flex-wrap: wrap;
  max-width: 500px;
}

.list-item{
  background-color: #ccc;
  display: flex;
  padding: 0.5em;
  width: 25%;
  margin-right: 1%;
  margin-bottom: 20px;
}
.list-content{
  width: 100%;
}
p{height:100px;overflow:hidden;}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
    <h2>box 1</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  
    <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor</p>
    </div>
  </li>
  
    <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>
</ul>

Ajay Malhotra
la source
Cela ne semble pas la réponse que je recherche, si le contenu devient plus grand, il sera caché.
Jinu Kurian
@JinuKurian où j'ajoute overflow: hidden, Si vous changez cela en overflow: auto, le défilement apparaîtra. alors vous pouvez également voir le contenu complet
Ajay Malhotra
-6

pour la même hauteur, vous devez modifier vos propriétés "d'affichage" css. Pour plus de détails, voir l'exemple donné.

.list{
  display: table;
  flex-wrap: wrap;
  max-width: 500px;
}

.list-item{
  background-color: #ccc;
  display: table-cell;
  padding: 0.5em;
  width: 25%;
  margin-right: 1%;
  margin-bottom: 20px;
}
.list-content{
  width: 100%;
}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
    <h2>box 1</h2>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. </p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  
    <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor</p>
    </div>
  </li>
  
    <li class="list-item">
    <div class="list-content">
    <h3>box 2</h3>
    <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>

Ankit
la source
Merci mais je veux afficher les listes sur plusieurs lignes.
Jinu Kurian