Flex-box: aligner la dernière ligne sur la grille

380

J'ai une disposition simple de boîte flexible avec un conteneur comme:

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

Maintenant, je veux que les éléments de la dernière ligne soient alignés avec l'autre. justify-content: space-between;doit être utilisé car la largeur et la hauteur de la grille peuvent être ajustées.

Actuellement, il ressemble

L'élément en bas à droite doit être au milieu

Ici, je veux que l'article en bas à droite soit dans la "colonne du milieu". Quelle est la façon la plus simple d'y parvenir? Voici un petit jsfiddle qui montre ce comportement.

.exposegrid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.exposetab {
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>

Thorben Croisé
la source
Vérifiez ma solution ici, je pense que cela fonctionne bien sans pirater, juste des maths: stackoverflow.com/questions/18744164/…
Sebastien Lorber
5
Alternativement, l'utilisation pourrait utiliser le nouveau module de grille css - qui n'a pas ce problème
Danield
1
J'ai ajouté une solution JS générique pour les cas où la largeur de l'enfant est variable, ce qui rend également le nombre d'éléments sur la ligne variable.
tao

Réponses:

417

Ajoutez un ::afterqui remplit automatiquement l'espace. Pas besoin de polluer votre HTML. Voici un codepen le montrant: http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid::after {
  content: "";
  flex: auto;
}
Dan Andreasson
la source
17
Serait-il possible de le faire fonctionner avec l'espace autour d'une manière ou d'une autre?
Tom
61
@DanAndreasson Il y a deux problèmes, il ne démarre pas à gauche (comme l'espace entre les deux), et aussi l'espace entre les éléments de la dernière ligne est différent de celui de la ligne précédente (simulant certains éléments de largeur fixe dans "n'importe quelle taille" grille - concerne les deux) ... codepen.io/anon/pen/gPoYZE Ce que je voulais, c'est maintenir la "stratégie" (espace autour ou espace entre) mais partir de la gauche comme sur les lignes précédentes ... I je voulais savoir, s'il est possible de généraliser votre solution étonnante.
Tom
44
Cela ne fonctionne que parce que les éléments ont leur rembourrage à l' espace et les largeurs de pourcentage combiné égal ou supérieur à 100% pour chaque ensemble de 4. Dans ce codepen j'ai retiré justify-content: space-between;de .gridet retiré .grid:afteret il fonctionne de la même. Maintenant, si vous essayez quelque chose comme ça, ça casse totalement. Remarquez que les largeurs pour chaque ensemble de 4 ne totalisent pas 100%. Dans le violon de l' OP, les largeurs sont définies en px, de sorte que votre solution ne fonctionne pas dans cette situation.
Jacob Alvarez
22
En essayant cette solution, au départ, les éléments avec lesquels il manquait sur la dernière ligne n'étaient pas correctement répartis space-between. Cependant, lorsque j'ai défini le flex-basisof .grid:aftersur le même dimensionnement que les autres éléments de la grille (par point d'arrêt, en remplaçant le code de module par défaut / de base ci-dessus), la dernière ligne s'est étalée correctement. Semble fonctionner sur Safari, iOS, Firefox, Chrome (besoin de tester IE) et ma plus grande taille de ligne est de 3 sur ma mise en œuvre initiale.
webbower
8
Pour mes besoins, cela a fonctionné avec la modification suivante: { content: "";flex: 0 0 32%;max-width: 480px;}et j'ai changé la largeur maximale avec des changements de requête de média afin que la grille soit parfaite à toutes les largeurs.
Colin Wiseman
161

Une technique consisterait à insérer un certain nombre d'éléments supplémentaires (autant que le nombre maximal d'éléments que vous vous attendez à avoir dans une rangée) qui reçoivent une hauteur nulle. L'espace est toujours divisé, mais les rangées superflues se réduisent à rien:

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

À l'avenir, cela peut devenir réalisable en utilisant plusieurs ::after(n).

Dalgard
la source
11
Malheureusement, cela contamine le balisage de manière non sémantique, mais cela fonctionne totalement. : SI j'aurais aimé connaître une autre façon de reproduire ce comportement, flexbox ou autre, qui ne nécessitait pas les éléments non sémantiques.
Ryan Norbauer
33
D'accord, c'est sale, mais ça marche, et c'est moins hacky que beaucoup de hacks. Feck it, je l'utilise, jusqu'à ce que :: after (12) gagne du support, ou qu'ils ajoutent des options de justification supplémentaires. C'est vraiment dommage car la façon dont Flexbox justifie le travail en ce moment est tout simplement fausse! Si vous justifiez un paragraphe de texte, vous n'essayez jamais de justifier la dernière ligne. Cela aurait certainement dû être une option, je ne peux pas croire qu'ils aient raté cela.
Codemonkey
4
Je suis venu avec une solution CSS uniquement .. la mise en garde étant qu'elle ne peut jamais représenter que deux éléments manquants, elle ne fonctionnera donc en toute sécurité que dans une grille flexible avec un maximum de trois éléments par ligne d'habillage. Démo: codepen.io/lukejacksonn/pen/dozqVq Le principe ici est d'utiliser des pseudo-éléments comme enfants supplémentaires et de leur donner la même propriété flex que les éléments du conteneur.
lukejacksonn
8
@Codemonkey Jesus. J'ai seulement commencé à utiliser Flexbox en pensant comment je vais me débarrasser de tous ces hacks destinés à aligner ces blocs en ligne à l'intérieur d'une grille, et maintenant il s'avère que ce n'est tout simplement pas possible! J'ai frappé ce bloc tout de suite, atteignant les limites que je pensais que j'atteindrais rarement avec bonheur en résolvant tous ces vieux problèmes CSS insolubles. Pas si vite, je suppose. Il n'a fallu que 20 ans pour obtenir un bon centrage vertical - nous pouvons certainement attendre. Jésus, la tâche semble si simple ...
Andrey
3
@dalgard Je ne pense pas. Voir mon commentaire .
Jacob Alvarez
109

Comme d'autres affiches l'ont mentionné - il n'y a aucun moyen propre d'aligner à gauche la dernière ligne avec flexbox (au moins selon la spécification actuelle)

Cependant, pour ce que ça vaut: avec le module de disposition de grille CSS c'est étonnamment facile à produire:

Fondamentalement, le code pertinent se résume à ceci:

ul {
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */
}

1) Faire de l'élément conteneur un conteneur de grille

2) Définissez la grille avec des colonnes automatiques de largeur 100px. (Notez l'utilisation du remplissage automatique (tel qu'apposé à auto-fit- qui (pour une mise en page à une ligne) réduit les pistes vides à 0 - ce qui entraîne l'expansion des éléments pour occuper l'espace restant. Cela entraînerait un «espace entre 'disposition lorsque la grille n'a qu'une seule ligne, ce qui dans notre cas n'est pas ce que nous voulons. (consultez cette démo pour voir la différence entre eux)).

3) Définissez les espaces / gouttières pour les lignes et les colonnes de la grille - ici, car vous voulez une disposition `` espace entre '' - l'écart sera en fait un écart minimum car il augmentera si nécessaire.

4) Similaire à la flexbox.

Codepen Demo (redimensionner pour voir l'effet)

Danield
la source
4
Belle solution. Le seul problème est qu'il ne fonctionne pas avec IE10 / 11.
zendu
1
Concernant auto-fit, il y avait un bug dans Chrome 57-60 (et les navigateurs basés sur son moteur, comme Samsung Internet 6.0) car la spécification était un peu ambiguë à l'époque. Maintenant, les spécifications ont été clarifiées et les nouvelles versions de Chrome s'affichent auto-fitcorrectement, mais les navigateurs avec l'ancien moteur sont toujours utilisés, alors soyez prudent avec cette valeur.
Ilya Streltsyn
4
À la lumière des possibilités actuelles, cela devrait maintenant être la réponse acceptée. L'utilisation d'un :afterpseudo-élément peut entraîner des résultats indésirables dans les cas de bord.
Paul
2
@ Danield, cette suggestion m'a beaucoup aidé, merci!
Krys
4
Ce devrait être la réponse acceptée. Je le combinerais avec flexbox comme solution de rechange, dans un esprit d'amélioration progressive: les navigateurs qui ne prennent pas en charge la grille afficheraient la version flexbox, qui est suffisamment proche pour moi.
Palantir
27

Sans aucun balisage supplémentaire, l'ajout a simplement ::afterfonctionné pour moi en spécifiant la largeur de la colonne.

.grid {
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
}
.grid::after{
  content: '';
  width: 10em // Same width of .grid__element
}
.grid__element{
  width:10em;
}

Avec le HTML comme ceci:

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>
Nicolás Arévalo
la source
9
c'est intéressant, mais pas tout à fait correct. le problème survient lorsque vous traitez avec plus de deux éléments dans la rangée du bas - l'espacement qui émerge entre les éléments sur les rangées ci-dessus n'émerge jamais sur le dernier; les articles sont emballés ensemble, annulant l'utilité d'origine de l'espace entre les deux.
John Haugeland
encore mieux si vous utilisez à la flex-basis: 10emplace de la largeur.
beytarovski du
14

Tu ne peux pas. Flexbox n'est pas un système de grille. Il n'a pas les constructions de langage pour faire ce que vous demandez, du moins pas si vous l'utilisez justify-content: space-between. Le plus proche que vous pouvez obtenir avec Flexbox est d'utiliser l'orientation des colonnes, ce qui nécessite de définir une hauteur explicite:

http://cssdeck.com/labs/pvsn6t4z (remarque: préfixes non inclus)

ul {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;
}

Cependant, il serait plus simple d'utiliser simplement des colonnes, qui ont un meilleur support et ne nécessitent pas de définir une hauteur spécifique:

http://cssdeck.com/labs/dwq3x6vr (remarque: préfixes non inclus)

ul {
  columns: 15em;
}
cimmanon
la source
2
Il y a un moyen; voir ma réponse.
Dalgard
@dalgard, votre réponse est une solution de contournement, pas une vraie solution. la réponse de cimmanon est correcte.
Jonas
1
@Jonah Je pense que "technique" est une bonne description de ma réponse. Cela a certainement fonctionné comme une solution pour beaucoup de gens, y compris le demandeur.
Dalgard
2
@dalgard Cela ne change pas le fait que Flexbox ne fournit pas les constructions de langage pour faire ce qui est demandé. De plus, je dirais que l'ajout de faux éléments est une pratique extrêmement sale, avec l'utilisation de tableaux pour la mise en page.
cimmanon
4
Ce n'est pas joli, mais le développement frontal est l'art du possible; le pragmatisme est une prémisse de base. Je pense que le mot est extrêmement déplacé, car des éléments supplémentaires sont utilisés pour le style sur 99,9% des sites Web du monde réel (cf. éléments de conteneur Bootstrap).
Dalgard
12

Une solution possible consiste à utiliser justify-content: flex-start; sur le .gridconteneur, des restrictions de taille sur ses enfants et des marges sur les éléments enfants appropriés - en fonction du nombre de colonnes souhaité.

Pour une grille à 3 colonnes, le CSS de base ressemblerait à ceci:

.grid {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}

.grid > * {
    flex: 0 0 32%;
    margin: 1% 0;
}

.grid > :nth-child(3n-1) {
    margin-left: 2%;
    margin-right: 2%;
}

C'est une autre solution imparfaite, mais cela fonctionne.

http://codepen.io/tuxsudo/pen/VYERQJ

Jared
la source
11

Je sais qu'il y a beaucoup de réponses ici mais .. La façon la plus simple de le faire est avec un gridau lieu de flexet grid template columnsavec repeatet auto fills, où vous devez définir le nombre de pixels que vous avez donné à chaque élément, à 100pxpartir de votre code d'extrait.

.exposegrid {
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;
}
 .exposetab {
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
}
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>

Surfeur d'Argent
la source
2
C'est la bonne solution pour aligner à gauche les éléments de la dernière ligne.
a.barbieri
Je suis d'accord, la bonne façon est d'utiliser la grille. Cela peut être réalisé avec Flexbox mais beaucoup plus propre à utiliser la grille.
nbarth
6

Oui.! Nous pouvons le faire, mais avec certaines requêtes multimédias et aucun nombre maximum de colonnes n'est prédéfini .

Ici, j'utilise 4 colonnes. Vérifiez mon code:

.container {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -moz-flex-flow: row wrap;
}

.container .item {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  justify-content: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
}

.container .item .item-child {
  width: 130px;
  height: 180px;
  background: red;
  margin: 10px;
}

@media (max-width: 360px) {
  .container .item {
    flex-basis: 100%;
  }
}

@media (min-width:360px) and (max-width: 520px) {
  .container .item {
    flex-basis: 50%;
  }
}

@media (min-width:520px) and (max-width: 680px) {
  .container .item {
    flex-basis: 33.33%;
  }
}
<div class="container">

  <div class="item">
    <div class="item-child">1</div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>

</div>

NOTE
1) Pas besoin de créer de div enfant. Il peut s'agir de n'importe quelle autre balise comme 'img' r ce que vous voulez.
2) Si vous voulez plus de colonnes, ajustez les requêtes multimédias et le nombre maximum de colonnes.

Mohamed Mohaideen AH
la source
Cela ne crée que 3 dans le dernier IE
Akxe
6

Si vous voulez une grille avec un espace entre les éléments et les éléments commençant sans espace initial, cette solution simple fonctionne:

.grid {
    display: flex;
    flex-flow: row wrap;
    margin: 0 -5px; // remove the inital 5px space
    width: auto;
}
.grid__item {
    width: 25%;
    padding: 0 5px; // should be same as the negative margin above.
}

Si vous voulez l'espace initial de 5px, supprimez simplement la marge négative :) Simple.

https://jsfiddle.net/b97ewrno/2/

La réponse acceptée, bien que bonne, fait qu'il n'y a pas d'espace entre les éléments de la deuxième rangée.

OZZIE
la source
1
Surpris, cela n'a plus de votes positifs. C'est une belle approche qui appartient au musée Flex.
Eduardo La Hoz Miranda
1
@EduardoLaHozMiranda merci! Mais pourquoi "musée"? IE11 ne prend pas en charge la grille CSS et la plupart des sites doivent toujours le prendre en charge. + Certains gros temporisateurs du développement frontend affirment toujours qu'il existe différents cas d'utilisation pour la grille et la flexbox. Mais peut-être que vous vouliez juste dire que cela devrait être une partie importante de l'histoire du Web: D
OZZIE
1
MDR ouais. J'étais excité à l'époque. Je voulais juste dire que c'était une excellente et minimale prise sur ce problème.
Eduardo La Hoz Miranda
@dencey vous n'avez pas besoin de savoir que pour cette solution, c'est 25% donc max 4 par ligne, mais vous pouvez utiliser le pourcentage que vous voulez
OZZIE
@OZZIE Je veux dire que la largeur de l'élément est fixe (comme 100px), mais la largeur du conteneur est dynamique, donc les éléments par ligne sont dynamiques.
dencey
4

Si vous souhaitez aligner le dernier élément sur la grille, utilisez le code suivant:

Conteneur de grille

.card-grid {
  box-sizing: border-box;
  max-height: 100%;
  display: flex;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  justify-content: space-between;
  align-items: stretch;
  align-content: stretch;
  -webkit-box-align: stretch;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
}

.card-grid:after {
  content: "";
  flex: 1 1 100%;
  max-width: 32%;
}

Article dans la grille

.card {
  flex: 1 1 100%;
  box-sizing: border-box;
  -webkit-box-flex: 1;
  max-width: 32%;
  display: block;
  position: relative;

}

L'astuce consiste à définir la largeur maximale de l'élément égale à la largeur maximale de la grille .card: après.

Démo en direct sur Codepen

Frank Spin
la source
cthulu vous bénit ainsi que votre ordinateur
L422Y
3
Cette approche ne fonctionne pas lorsque la taille de la carte est fixe et que le nombre de cartes dans chaque ligne est inconnu. codepen.io/zendu/pen/WXNGvo
zendu
3

Il est possible d'utiliser "flex-start" et d'ajouter les marges manuellement. Il nécessite un peu de piratage mathématique, mais il est certainement facile à faire et à utiliser avec un préprocesseur CSS comme LESS.

Voir par exemple ce mixin MOINS:

.flexboxGridMixin(@columnNumber,@spacingPercent) {
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * {
    box-sizing: border-box;
    width: @contentPercent/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  }
}

Et puis, il peut facilement être utilisé pour afficher une disposition de grille réactive:

ul {
  list-style: none;
  padding: 0;
  @spacing: 10%;
  @media only screen and (max-width: 499px) { .flexboxGridMixin(1,@spacing); }
  @media only screen and (min-width: 500px) { .flexboxGridMixin(2,@spacing); }
  @media only screen and (min-width: 700px) { .flexboxGridMixin(3,@spacing); }
  @media only screen and (min-width: 900px) { .flexboxGridMixin(4,@spacing); }
  @media only screen and (min-width: 1100px) { .flexboxGridMixin(5,@spacing); }
}

li {
  background: pink;
  height: 100px;
  margin-top: 20px;
}

Voici un exemple de

http://codepen.io/anon/pen/YyLqVB?editors=110

Sébastien Lorber
la source
Vous n'utilisez jamais @contentPercent. En aviez-vous l'intention?
neverfox
width: @ contentPercent / @ columnNumber;
realtebo
HOU LA LA ! Je suis vraiment impressionné par cette solution. Je vais essayer de m'adapter à ma situation
realtebo
3

Ce problème a été résolu pour moi en utilisant la grille CSS,

Cette solution n'est applicable que si vous rencontrez un nombre fixe de colonnes, c'est-à-dire non. d'éléments à afficher sur une seule ligne

-> utilisant une grille mais ne spécifiant pas le nombre de lignes, comme le nombre d'éléments augmente, il s'enroule dans des colonnes et ajoute des lignes dynamiquement, j'ai spécifié trois colonnes dans cet exemple

-> vous n'avez pas à donner de position à votre enfant / cellules, car cela le rendra fixe, ce que nous ne voulons pas.

.grid-class{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 80px;
}

Ashwin
la source
1

Cette version est le meilleur moyen pour les blocs à largeur fixe:

http://codepen.io/7iomka/pen/oxxeNE

Dans d'autres cas - version de dalgard

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
justify-content:center;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  max-width:200px;
  min-width:200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

Znacovean Simion
la source
0

Il existe un moyen sans flexbox, bien que vous deviez remplir les conditions suivantes. 1) Le conteneur a un rembourrage. 2) Les articles sont de la même taille et vous savez exactement combien vous voulez par ligne.

ul {
  padding: 0 3% 0 5%;
}
li {
  display: inline-block; 
  padding: 0 2% 2% 0;
  width: 28.66%;
}

Le rembourrage plus petit sur le côté droit du conteneur permet le rembourrage supplémentaire à droite de chaque élément de la liste. En supposant que les autres éléments du même parent que l'objet de liste sont remplis de 0 à 5%, ils seront alignés avec eux. Vous pouvez également ajuster les pourcentages selon la marge souhaitée ou utiliser le calcul des valeurs px.

Bien sûr, vous pouvez faire de même sans le rembourrage sur le conteneur en utilisant nth-child (IE 9+) pour supprimer la marge sur une troisième boîte.

ansorensen
la source
0

En utilisant flexbox et quelques requêtes multimédias, j'ai fait ce petit contournement: http://codepen.io/una/pen/yNEGjv (c'est un peu hacky mais ça marche):

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  max-width: 1200px;
  margin: 0 auto;
}

.item {
  background-color: gray;
  height: 300px;
  flex: 0 30%;
  margin: 10px;

  @media (max-width: 700px) {
     flex: 0 45%;
  }

  @media (max-width: 420px) {
    flex: 0 100%;
  }

  &:nth-child(3n-1) {
    margin-left: 10px;
    margin-right: 10px;
  }
}
Una Kravets
la source
0

J'ai fait un mixage SCSS pour cela.

@mixin last-row-flexbox($num-columns, $width-items){

  $filled-space: $width-items * $num-columns;
  $margin: calc((100% - #{$filled-space}) / (#{$num-columns} - 1));

  $num-cols-1 : $num-columns - 1;

  &:nth-child(#{$num-columns}n+1):nth-last-child(-n+#{$num-cols-1}) ~ & {
    margin-left: $margin;
  }
  @for $i from 1 through $num-columns - 2 { 
    $index: $num-columns - $i;
    &:nth-child(#{$num-columns}n+#{$index}):last-child{
      margin-right: auto;
    }
  }
}

Ceci est le lien codepen: http://codepen.io/diana_aceves/pen/KVGNZg

Il vous suffit de définir la largeur des éléments en pourcentage et en nombre de colonnes.

J'espère que cela pourra vous aider.

Diane
la source
0

Voici un autre couple de mixins scss.

Ces mixins supposent que vous n'utiliserez pas de plugins js comme Isotope (ils ne respectent pas l'ordre de balisage html, gâchant ainsi les règles nss du CSS).

De plus, vous pourrez en profiter pleinement, surtout si vous écrivez vos points d'arrêt réactifs de manière mobile en premier. Vous utiliserez idéalement flexbox_grid () sur le plus petit point d'arrêt et flexbox_cell () sur les points d'arrêt suivants. flexbox_cell () se chargera de réinitialiser les marges précédemment définies qui ne sont plus utilisées sur les points d'arrêt plus grands.

Et en passant, tant que vous configurez correctement les propriétés flex de votre conteneur, vous pouvez également utiliser uniquement flexbox_cell () sur les éléments, si vous en avez besoin.

Voici le code:

// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $gutter_width){

  display: flex;
  flex-direction:row;
  flex-wrap:wrap;
  justify-content: flex-start;

  > *{
    @include flexbox_cell($columns, $gutter_width);
  }
}

// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $gutter_width){
  $base_width: 100 / $columns;
  $gutters: $columns - 1;
  $gutter_offset: $gutter_width * $gutters / $columns;

  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto; // IE10 doesn't support calc() here

  box-sizing:border-box; // so you can freely apply borders/paddings to items
  width: calc( #{$base_width}% - #{$gutter_offset} );

  // remove useless margins (for cascading breakponts)
  &:nth-child(#{$columns}n){
    margin-right: 0;
  }

  // apply margin
  @for $i from 0 through ($gutters){
    @if($i != 0){
      &:nth-child(#{$columns}n+#{$i}){
        margin-right: $gutter_width;
      }
    }
  }
}

Usage:

ul{
   // just this:
   @include flexbox_grid(3,20px);
}

// and maybe in following breakpoints, 
// where the container is already setted up, 
// just change only the cells:

li{
   @include flexbox_cell(4,40px);
}

De toute évidence, c'est à vous de définir éventuellement le remplissage / marge / largeur du conteneur et les marges inférieures de la cellule, etc.

J'espère que cela aide!

Luca Reghellin
la source
0

C'est assez hacky, mais ça marche pour moi. J'essayais d'obtenir un espacement / des marges cohérents.

.grid {
  width: 1024px;
  display: flex;
  flex-flow: row wrap;
  padding: 32px;
  background-color: #ddd;  

  &:after {
    content: "";
    flex: auto;
    margin-left:-1%;
  }

  .item {
    flex: 1 0 24.25%;
    max-width: 24.25%;
    margin-bottom: 10px;
    text-align: center;
    background-color: #bbb;

    &:nth-child(4n+2),
    &:nth-child(4n+3),
    &:nth-child(4n+4) {
      margin-left: 1%;
    }

    &:nth-child(4n+1):nth-last-child(-n+4),
      &:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
        margin-bottom: 0;
    }    

  }
}

http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/

RustyDev
la source
0

Il semble que personne n'ait proposé la solution flex-grow sur le dernier élément. L'idée est d'avoir votre dernier article flex pour prendre toute la place qu'il peut en utilisant flex-grow: 1.

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid > *:last-child {
  flex-grow: 1;
}

Remarque: Cette solution n'est pas parfaite, surtout si vous avez des éléments centrés à l'intérieur de vos éléments flexibles, car elle sera centrée sur le dernier élément flexible éventuellement énorme.

Dionys
la source
0

Ceci est une combinaison de beaucoup de réponses, mais il fait exactement ce dont j'avais besoin - qui est d'aligner le dernier enfant dans un conteneur flexible vers la gauche tout en conservant le comportement d'espace entre les deux (dans ce cas, il s'agit de trois colonnes disposition).

Voici le balisage:

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-direction: row;
}

.flex-container:after {
  content: "";
  flex-basis: 30%;
}
Margaret
la source
1
Pour être plus générique: la taille de la base flexible doit être égale à la taille des enfants.
Christian Toffolo
1
J'ai trouvé flex-grow: 0.9au lieu de flex-basistravaux pour un certain nombre de colonnes. Testé dans un tas de navigateurs modernes - il fonctionne dans tous mais le rembourrage est cassé dans IE (mais fonctionne dans Edge0
Patabugen
0

En supposant:

  • Vous voulez une disposition de grille à 4 colonnes avec habillage
  • Le nombre d'articles n'est pas nécessairement un multiple de 4

Définissez une marge gauche sur chaque élément sauf le 1er, le 5e et le 9e élément, etc. Si la marge de gauche est de 10 pixels, chaque ligne aura une marge de 30 pixels répartie sur 4 éléments. Le pourcentage de largeur pour l'article est calculé comme suit:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

Il s'agit d'une solution de contournement décente pour les problèmes impliquant la dernière ligne de flexbox.

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0 3em;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>

Salman A
la source
0

Si vous connaissez la largeur des espaces entre les éléments de la ligne et la quantité d'éléments dans une ligne, cela fonctionnerait:

Exemple: 3 éléments d'affilée, espace de 10 pixels entre les éléments

div:last-child:nth-child(3n+2) {
  flex-grow: 1
  margin-left: 10px
}
norweny
la source
0

Utilisez simplement l'astuce Jquery / Javascript pour ajouter un div vide:

if($('.exposegrid').length%3==2){
 $(".exposegrid").append('<div class="exposetab"></div>');
}
Waheed Mazhar
la source
-1

Oh boy, je pense que j'ai trouvé une bonne solution avec un minimum de CSS et pas de JS. Vérifiez-le:

img {width:100%;}
li {
  display: inline-block;
  width:8em;
  list-style:none;
}
ul {text-align: justify;}
<ul>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

La clé ici est de se rappeler que ce que nous essayons d'atteindre est exactement ce qui text-align: justifyfait!

Les éléments vides dans le HTML sont là pour que la dernière ligne s'affiche parfaitement sans changer l'apparence, mais peuvent ne pas être nécessaires compte tenu de ce que vous essayez de réaliser. Pour un équilibre parfait dans chaque situation, vous avez besoin d'au moins x-4 éléments vides, x étant le nombre d'éléments à afficher, ou n-2, n étant le nombre de colonnes que vous souhaitez afficher.

Sharcoux
la source
-1

Ajoutez simplement quelques faux articles avec les mêmes propriétés à l'exception de la hauteur définie à 0px à la fin.

Erik Parso
la source
L'ajout de faux articles est une mauvaise pratique dans tous les sens. Vous n'êtes pas censé remplir le DOM avec des trucs juste pour pirater les CSS sauf si c'est obligatoire. Pour de nombreuses raisons, de l'accessibilité, à l'inondation de la base de code avec des trucs bizarres, à rendre la logique plus complexe à comprendre et à répertorier. Ne recommandez pas les hacks sauf si vous dites explicitement que cela pourrait être une mauvaise solution ou qu'il y a un cas spécial pour cela.
Eksapsy
-4

tu veux aligner

utiliser align-content: flex-start;au lieu dejustify-content: space-between;

cela tire les éléments de la dernière ligne vers la gauche et répartit également l'espace de manière égale,

.container {
  display: flex;
  flex-flow: row wrap;
  align-content: flex-start;
  /*justify-content: space-between; remove this line!!!! */ 
}

https://codepen.io/anon/pen/aQggBW?editors=1100


La solution danAnderson n'est PAS DYNAMIQUE .PERİOD !!

lorsque la largeur de l'élément est passée de 25 à 28 dan anderson manque d'espace entre les images

danAnderson: https://codepen.io/anon/pen/ZwYPmB?editors=1100

dynamique: https://codepen.io/anon/pen/aQggBW?editors=1100

c'est ce que j'ai essayé de dire. dans est hacky .....

bh_earth0
la source
-7

J'ai pu le faire avec justify-content: space-betweensur le container

chovy
la source