Flexbox item — перенос на новую строку

1,00
р.
Есть Flexbox сетка.


.flex { display: flex flex-wrap: wrap border: 2px solid red } .item { width: 50px height: 50px margin: 5px border: 2px solid blue }


Как перенести .new-string на новую строку вместе с элементами, которые идут после него?

Ответ
Перевод ответа на enSO.
Примечание переводчика: flex-элемент (flex item) — непосредственный ребёнок блока с display: flex.

Наиболее простое и надёжное решение — это вставка flex-элементов в правильных местах. Если они достаточно широкие (width: 100%), они будут создавать перенос строки.


.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% }
1
2
3
4
5
6
7
8
9
10


Но это уродливо и не семантически. Вместо этого, мы можем генерировать псевдоэлементы внутры flex-контейнера и использовать свойство order чтобы перемещать их в нужные места.


.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 }
1
2
3
4
5
6
7
8
9


Но есть ограничение: flex-контейнер может иметь только псевдоэлементы ::before и ::after. Это значит, что мы можем создать только 2 переноса строки.
Чтобы разрешить это, вы можете генерировать псевдоэлементы внутри flex-элементов вместо flex-контейнера. Таким способом вы не будете ограничены двумя. Но эти псевдоэлементы не будут flex-элементами, поэтому не будут создавать переносы строк.
Но, к счастью, спецификация CSS Display L3 ввела display: contents (в данный момент поддерживаемая только Firefox 37):
Элемент сам по себе не генерирует никаких блоков, но его дети и псевдоэлементы генерируют блоки как обычно. С целью генерации блоков и разметки элемент будет расцениваться как будто он был заменён его детьми и псевдоэлементами в дереве документа.
Поэтому вы можете применять display: contents к детям flex-контейнера и обернуть содержимое каждого внутрь дополнительного блок. Таким образом flex-элементы будут этими дополнительными обёртками и псевдоэлементами детей.


.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% }
1
2
3
4
5
6
7
8
9
10


Кроме того, в соответствии с Fragmenting Flex Layout и CSS Fragmentation, flexbox позволяет принудительные переносы с помощью break-before, break-after или их псевдонимов в CSS 2.1:
.item:nth-child(3n) { page-break-after: always /* Синтаксис CSS 2.1 */ break-after: always /* Новый синтаксис */ }


.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 }
1
2
3
4
5
6
7
8
9
10


Принудительные переносы строк во flexbox ещё широко не поддерживаются, но они работают в Firefox.