A solução mais simples e confiável é inserir itens flexíveis nos lugares certos. Se tiverem largura suficiente ( width: 100%
), forçarão uma quebra de linha.
.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>
Mas isso é feio e não semântico. Em vez disso, poderíamos gerar pseudoelementos dentro do contêiner flex e usá order
-los para movê-los para os lugares certos.
.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>
Mas há uma limitação: o contêiner flex pode ter apenas um ::before
e um ::after
pseudo-elemento. Isso significa que você só pode forçar duas quebras de linha.
Para resolver isso, você pode gerar os pseudoelementos dentro dos itens flex, em vez de no contêiner flex. Dessa forma, você não ficará limitado a 2. Mas esses pseudoelementos não serão itens flexíveis, portanto não poderão forçar quebras de linha.
Mas, felizmente, o CSS Display L3 introduziu display: contents
(atualmente suportado apenas pelo Firefox 37):
O próprio elemento não gera caixas, mas seus filhos e pseudo-elementos ainda geram caixas normalmente. Para fins de geração e layout de caixas, o elemento deve ser tratado como se tivesse sido substituído por seus filhos e pseudo-elementos na árvore de documentos.
Assim, você pode aplicar display: contents
aos filhos do contêiner flex e envolver o conteúdo de cada um dentro de um invólucro adicional. Então, os itens flexíveis serão os invólucros adicionais e os pseudoelementos das crianças.
.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>
Alternativamente, de acordo com Fragmentar Flex Disposição e fragmentação CSS , Flexbox permite quebras forçado usando break-before
, break-after
ou os seus nomes alternativos 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>
As quebras de linha forçadas no flexbox ainda não são amplamente suportadas, mas funcionam no Firefox.