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; */
}
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.
@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>
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.
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:
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 !!
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>
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>