You are correct by specifying a flex-basis: 20%
, but it's important to account for the 4px margin on each flex item in order for it to wrap properly.
Ensuring Equal Width Flex items in the Last Row
To achieve this, use flex: 0 1 calc(20% - 8px)
- which ensures the item won't exceed 20% of width (adjusted for margin) and can shrink based on the container width. See the demonstration below:
.container {
background: gray;
width: 600px;
height: 200px; /* height specified for illustration purposes */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 0 1 calc(20% - 8px); /* <-- adjustment for margin */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Another alternative involves setting flex-grow
to one and using flex-basis: calc(20% - 4px)
with flex: 1 1 calc(20% - 4px)
, paired with a pseudo-element that fills the remaining space:
.container {
background: gray;
width: 600px;
height: 200px; /* height specified for illustration purposes */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 1 1 calc(20% - 8px); /* <-- adjustment for margin */
}
.container:after {
content: '';
display: block;
flex: 999; /* large growth factor */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
If you do not have the requirement of having a specific number of items per row, you may find this useful:
- Unordered list that acts like grid-auto-flow dense
Expanding Flex Items in the Last Row to Fill Available Space
In scenarios where there are fewer than 5 items in a row and you want them to occupy the available space, utilize flex: 1 1 calc(20% - 8px)
where flex-grow
is set to 1 allowing the flex items in the last rows to expand and fill the remaining space:
.container {
background: gray;
width: 600px;
height: 200px; /* height specified for illustration purposes */
display: flex;
flex-flow: row wrap;
position: relative;
}
.item {
background: blue;
margin: 4px;
flex: 1 1 calc(20% - 8px); /* <-- adjustment for margin */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>