How to start a new column in flex column wrap layout
Apparently, the correct solution is to use the break-before
or break-after
property:
A break is forced wherever the CSS2.1 page-break-before/page-break-after [CSS21] or the CSS3 break-before/break-after [CSS3-BREAK] properties specify a fragmentation break.
At the time of writing, most browsers implement the *-break-*
properties incorrectly or do not implement them at all. Consider this answer ahead of its time.
The following demo works in:
- FF33
.grid {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.grid .head {
width: 25%;
background: orange;
border-bottom: thin dotted;
}
.grid .data {
width: 25%;
background: yellow;
border-bottom: thin dotted;
}
/* force column breaks */
.grid .head:nth-child(n + 2) {
page-break-before: always; /* FF33 */
}
<div class="grid">
<div class="head">Column 1 (3 items)</div>
<div class="data">item 1-1</div>
<div class="data">item 1-2</div>
<div class="data">item 1-3</div>
<div class="head">Column 2 (4 items)</div>
<div class="data">item 2-1</div>
<div class="data">item 2-2</div>
<div class="data">item 2-3</div>
<div class="data">item 2-4</div>
<div class="head">Column 3 (2 items)</div>
<div class="data">item 3-1</div>
<div class="data">item 3-2</div>
<div class="head">Column 4 (1 items)</div>
<div class="data">item 4-1</div>
</div>
If you can dynamically add a div before each head (except the first), it may be possible. Credits go to Tobias Bjerrome Ahlin. Tested on Chrome, Firefox, Safari and IE11.
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 200px;
}
.item {
background-color: #A2CBFA;
border: 1px solid #4390E1;
margin: 2px;
}
.break {
flex-basis: 100%;
}
<div class="container">
<div class="item">item 1</div>
<div class="item">item 2</div>
<div class="break"></div>
<div class="item">item 3</div>
<div class="item">item 4</div>
<div class="item">item 5</div>
<div class="break"></div>
<div class="item">item 6</div>
<div class="break"></div>
<div class="item">item 7</div>
<div class="item">item 8</div>
</div>
I don't think there is a way to do this with flexbox, however, if we use column-count
we can take advantage of the properties:
‘break-before’, ‘break-after’, ‘break-inside’
In particular:
We can set break-before: column;
on each 'head' element, where the column value means:
Always force a column break before the generated box.
(similarly if we were using break-after:column this would force a column break after the generated box )
NB: Browser support is currently limited to IE (!!)
.grid {
columns: 4;
column-gap: 0;
}
.grid > div {
background: lightyellow;
border-bottom: thin dotted;
}
.grid .head {
background: gold;
border-bottom: thin dotted;
break-before: column; /* ð this is the vital rule */
}
@media screen and (min-width:0\0) {
.grid {
position: relative;
left:-20vw;
/* Probably because IE wants to add a column before the first head class??
Interestingly enough though, the following selector does not work:
.data + .head { break-before: column; } */
}
}
<div class="grid">
<div class="head">Column 1 (3 items)</div>
<div>item 1-1</div>
<div>item 1-2</div>
<div>item 1-3</div>
<div class="head">Column 2 (4 items)</div>
<div>item 2-1</div>
<div>item 2-2</div>
<div>item 2-3</div>
<div>item 2-4</div>
<div class="head">Column 3 (2 items)</div>
<div>item 3-1</div>
<div>item 3-2</div>
<div class="head">Column 4 (1 items)</div>
<div>item 4-1</div>
</div>
--
Note that in the above fiddle for IE there seems to be a positioning issue (bug?) so I placed some code in a special media query that only effects IE so as not to effect other browsers