web-dev-qa-db-fra.com

Comment spécifier des sauts de ligne dans une présentation flexbox multiligne?

Existe-t-il un moyen de changer de ligne dans une flexbox à plusieurs lignes?

Par exemple, casser après chaque 3ème élément dans this CodePen .

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  height: 100px;
  background: gold;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
.item:nth-child(3n) {
  background: silver;
}
<div class="container">
  <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 class="item">10</div>
</div>

Comme

.item:nth-child(3n){
  /* line-break: after; */    
}
191
Artem Svirskyi

La solution la plus simple et la plus fiable consiste à insérer des éléments flexibles aux bons endroits. S'ils sont suffisamment larges (_width: 100%_), ils forceront un saut de ligne.

_.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}
.item:nth-child(4n - 1) {
  background: silver;
}
.line-break {
  width: 100%;
}_
_<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="line-break"></div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="line-break"></div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
  <div class="line-break"></div>
  <div class="item">10</div>
</div>_

Mais c'est moche et pas sémantique. Au lieu de cela, nous pourrions générer des pseudo-éléments à l'intérieur du conteneur flex et utiliser order pour les déplacer aux bons endroits.

_.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}
.item:nth-child(3n) {
  background: silver;
}
.container::before, .container::after {
  content: '';
  width: 100%;
  order: 1;
}
.item:nth-child(n + 4) {
  order: 1;
}
.item:nth-child(n + 7) {
  order: 2;
}_
_<div class="container">
  <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>_

Mais il y a une limitation: le conteneur flex ne peut avoir qu'un pseudo-élément _::before_ et _::after_. Cela signifie que vous ne pouvez forcer que 2 sauts de ligne.

Pour résoudre ce problème, vous pouvez générer les pseudo-éléments dans les éléments flex plutôt que dans le conteneur flex. De cette façon, vous ne serez pas limité à 2. Mais ces pseudo-éléments ne seront pas des éléments flexibles et ne pourront donc pas forcer des sauts de ligne.

Mais heureusement, CSS Display L a introduit display: contents (uniquement supporté par Firefox 37):

L'élément lui-même ne génère aucune boîte, mais ses enfants et ses pseudo-éléments continuent de générer des boîtes normalement. Aux fins de la création de boîtes et de la présentation, l'élément doit être traité comme s'il avait été remplacé par ses enfants et ses pseudo-éléments dans l'arborescence du document.

Vous pouvez donc appliquer _display: contents_ aux enfants du conteneur Flex et envelopper le contenu de chacun dans un wrapper supplémentaire. Ensuite, les éléments flex seront ces wrappers supplémentaires et les pseudo-éléments des enfants.

_.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  display: contents;
}
.item > div {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
.item:nth-child(3n) > div {
  background: silver;
}
.item:nth-child(3n)::after {
  content: '';
  width: 100%;
}_
_<div class="container">
  <div class="item"><div>1</div></div>
  <div class="item"><div>2</div></div>
  <div class="item"><div>3</div></div>
  <div class="item"><div>4</div></div>
  <div class="item"><div>5</div></div>
  <div class="item"><div>6</div></div>
  <div class="item"><div>7</div></div>
  <div class="item"><div>8</div></div>
  <div class="item"><div>9</div></div>
  <div class="item"><div>10</div></div>
</div>_

Alternativement, selon Fragmenting Flex Layout et CSS Fragmentation , Flexbox autorise les pauses forcées à l'aide de break-before , break-after ou leurs alias CSS 2.1:

_.item:nth-child(3n) {
  page-break-after: always; /* CSS 2.1 syntax */
  break-after: always; /* New syntax */
}
_
_.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}
.item:nth-child(3n) {
  page-break-after: always;
  background: silver;
}_
_<div class="container">
  <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 class="item">10</div>
</div>_

Les sauts de ligne forcés dans flexbox ne sont pas encore largement pris en charge, mais cela fonctionne sous Firefox.

279
Oriol

@Oriol a une excellente réponse, malheureusement, à partir d'octobre 2017, ni display:contents, ni page-break-after ne sont pas largement pris en charge. Mieux dit, il s'agit de Firefox qui prend en charge cette fonctionnalité, mais pas celle des autres joueurs. après "bidouille" que je considère mieux que coder dur lors d’une pause après chaque 3ème élément, car il sera très difficile de rendre la page conviviale pour les mobiles.

Comme dit plus haut, l’inconvénient est qu’il faut ajouter pas mal d’éléments supplémentaires pour rien, mais c’est efficace et cela fonctionne entre navigateurs même sur IE1 daté.

Le "hack" consiste simplement à ajouter un élément supplémentaire après chaque div, qui est défini sur display:none puis utilisé le css nth-child pour décider lequel de ces éléments doit être rendu visible, forçant un frein de ligne comme cette:

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}
.item:nth-child(3n-1) {
  background: silver;
}
.breaker {display:none;}
.breaker:nth-child(3n) {
  display:block;
  width:100%;
  height:0;
 }
<div class="container">
  <div class="item">1</div><p class=breaker></p>
  <div class="item">2</div><p class=breaker></p>
  <div class="item">3</div><p class=breaker></p>
  <div class="item">4</div><p class=breaker></p>
  <div class="item">5</div><p class=breaker></p>
  <div class="item">6</div><p class=breaker></p>
  <div class="item">7</div><p class=breaker></p>
  <div class="item">8</div><p class=breaker></p>
  <div class="item">9</div><p class=breaker></p>
  <div class="item">10</div><p class=breaker></p>
</div>
21
Emil Borconi

De mon point de vue, il est plus sémantique d'utiliser <hr>des éléments comme des sauts de ligne entre les éléments flexibles.

<div class="container">
  <div>1</div>
  <div>2</div>
  <hr>
  <div>3</div>
  <div>2</div>
  ...
</div>

Le CSS suit

.container {
  display: flex;
  flex-flow: wrap;
}

.container hr {
  width: 100%;
}

Testé dans Chrome 66, Firefox 60 et Safari 11.

21
Petr Stepanov

Vous voulez un saut de ligne sémantique?

Ensuite, envisagez d'utiliser <br>. W3Schools peut vous suggérer que BR soit juste pour écrire des poèmes (le mien arrive bientôt), mais vous pouvez changer le style pour qu'il se comporte comme un élément de bloc de 100% de la largeur qui repoussera votre contenu à la ligne suivante. Si 'br' suggère une pause, cela me semble plus approprié que d'utiliser hr ou un 100% div et rend le code HTML plus lisible.

Insérez le <br> où vous avez besoin de sauts de ligne et appelez-le ainsi.

 // Use `>` to avoid styling `<br>` inside your boxes 
 .container > br 
 {
    width: 100%;
    content: '';
 }

Vous pouvez désactiver <br> avec les requêtes sur les supports , en définissant display: sur block ou none selon le cas (j’en ai inclus un exemple, mais laissé commenté).

Vous pouvez utiliser order: pour définir l'ordre si nécessaire.

Et vous pouvez en mettre autant que vous voulez, avec des classes ou des noms différents :-)

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}
.item {
  width: 100px;
  background: gold;
  height: 100px;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px
}

.container > br
{
  width: 100%;
  content: '';
}

// .linebreak1 
// { 
//    display: none;
// }

// @media (min-width: 768px) 
// {
//    .linebreak1
//    {
//       display: block;
//    }
// }
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <br class="linebreak1"/>
  <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 class="item">10</div>
</div>

Inutile de vous limiter à ce que dit W3Schools:

enter image description here

9
Simon_Weaver

Je pense que la méthode traditionnelle est flexible et assez facile à comprendre:

Balisage

<div class="flex-grid">
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>

    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>
    <div class="col-4">.col-4</div>

    <div class="col-3">.col-3</div>
    <div class="col-9">.col-9</div>

    <div class="col-6">.col-6</div>
    <div class="col-6">.col-6</div>
</div>

Créer un fichier grid.css :

.flex-grid {
  display: flex;
  flex-flow: wrap;
}

.col-1 {flex: 0 0 8.3333%}
.col-2 {flex: 0 0 16.6666%}
.col-3 {flex: 0 0 25%}
.col-4 {flex: 0 0 33.3333%}
.col-5 {flex: 0 0 41.6666%}
.col-6 {flex: 0 0 50%}
.col-7 {flex: 0 0 58.3333%}
.col-8 {flex: 0 0 66.6666%}
.col-9 {flex: 0 0 75%}
.col-10 {flex: 0 0 83.3333%}
.col-11 {flex: 0 0 91.6666%}
.col-12 {flex: 0 0 100%}

[class*="col-"] {
  margin: 0 0 10px 0;

  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

@media (max-width: 400px) {
  .flex-grid {
    display: block;
  }
}

J'ai créé un exemple (jsfiddle)

Essayez de redimensionner la fenêtre sous 400px, c'est réactif !!

6
Moshe Quantz

Une autre solution possible qui ne nécessite l'ajout de balises consiste à ajouter une marge dynamique pour séparer les éléments.

Dans le cas de l'exemple, cela peut être fait à l'aide de calc(), en ajoutant simplement margin-left et margin-right à l'élément 3n + 2 (2, 5, 8).

.item:nth-child(3n+2) {
  background: silver;
  margin: 10px calc(50% - 175px);
}

Exemple d'extrait

.container {
  background: tomato;
  display: flex;
  flex-flow: row wrap;
  align-content: space-between;
  justify-content: space-between;
}
.item {
  width: 100px;
  height: 100px;
  background: gold;
  border: 1px solid black;
  font-size: 30px;
  line-height: 100px;
  text-align: center;
  margin: 10px;
}
.item:nth-child(3n+2) {
  background: silver;
  margin: 10px calc(50% - 175px);
}
<div class="container">
  <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 class="item">10</div>
</div>
1
Juanma Menendez

Pour les questions futures, il est également possible de le faire en utilisant la propriété float et en la désactivant dans chacun des 3 éléments.

Voici un exemple que j'ai fait.

.grid {
  display: inline-block;
}

.cell {
  display: inline-block;
  position: relative;
  float: left;
  margin: 8px;
  width: 48px;
  height: 48px;
  background-color: #bdbdbd;
  font-family: 'Helvetica', 'Arial', sans-serif;
  font-size: 14px;
  font-weight: 400;
  line-height: 20px;
  text-indent: 4px;
  color: #fff;
}

.cell:nth-child(3n) + .cell {
  clear: both;
}
<div class="grid">
  <div class="cell">1</div>
  <div class="cell">2</div>
  <div class="cell">3</div>
  <div class="cell">4</div>
  <div class="cell">5</div>
  <div class="cell">6</div>
  <div class="cell">7</div>
  <div class="cell">8</div>
  <div class="cell">9</div>
  <div class="cell">10</div>
</div>
0
Gabriel