I have a simple flex-box layout with a container like:
.grid {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
}
Yes.! We can but with some media queries & Maximum no of columns are predefined.
Here am using 4 columns. Check my code:
.container {
display: flex;
display: -webkit-flex;
display: -moz-flex;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
}
.container .item {
display: flex;
display: -webkit-flex;
display: -moz-flex;
justify-content: center;
-webkit-justify-content: center;
-moz-justify-content: center;
flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
}
.container .item .item-child {
width: 130px;
height: 180px;
background: red;
margin: 10px;
}
@media (max-width: 360px) {
.container .item {
flex-basis: 100%;
}
}
@media (min-width:360px) and (max-width: 520px) {
.container .item {
flex-basis: 50%;
}
}
@media (min-width:520px) and (max-width: 680px) {
.container .item {
flex-basis: 33.33%;
}
}
<div class="container">
<div class="item">
<div class="item-child">1</div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
<div class="item">
<div class="item-child"></div>
</div>
</div>
NOTE
1) No need to create child div. It may be any other tag like 'img' r whatever you want..
2) If you want more columns adjust the media queries and maximum no.of columns.
As other posters have mentioned - there's no clean way to left-align the last row with flexbox (at least as per the current spec)
However, for what it's worth: With the CSS Grid Layout Module this is surprisingly easy to produce:
Basically the relevant code boils down to this:
ul {
display: grid; /* 1 */
grid-template-columns: repeat(auto-fill, 100px); /* 2 */
grid-gap: 1rem; /* 3 */
justify-content: space-between; /* 4 */
}
1) Make the container element a grid container
2) Set the grid with auto columns of width 100px. (Note the use of auto-fill (as apposed to auto-fit
- which (for a 1-row layout) collapses empty tracks to 0 - causing the items to expand to take up the remaining space. This would result in a justified 'space-between' layout when grid has only one row which in our case is not what we want. (check out this demo to see the difference between them)).
3) Set gaps/gutters for the grid rows and columns - here, since want a 'space-between' layout - the gap will actually be a minimum gap because it will grow as necessary.
4) Similar to flexbox.
ul {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
grid-gap: 1rem;
justify-content: space-between;
/* boring properties */
list-style: none;
background: wheat;
padding: 2rem;
width: 80vw;
margin: 0 auto;
}
li {
height: 50px;
border: 1px solid green;
}
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Here's another couple of scss mixins.
These mixins assume that you are not going to use js plugins like Isotope (they don't respect html markup order, thus messing up with css nth rules).
Also, you will be able to take full advantage of them especially if you're writing your responsive breakpoints in a mobile first manner. You ideally will use flexbox_grid() on the smaller breakpoint and flexbox_cell() on the following breakpoints. flexbox_cell() will take care of resetting previously setted margins no longer used on larger breakpoints.
And by the way, as long as you correctly setup your container's flex properties, you can also use only flexbox_cell() on the items, if you need to.
Here's the code:
// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $gutter_width){
display: flex;
flex-direction:row;
flex-wrap:wrap;
justify-content: flex-start;
> *{
@include flexbox_cell($columns, $gutter_width);
}
}
// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $gutter_width){
$base_width: 100 / $columns;
$gutters: $columns - 1;
$gutter_offset: $gutter_width * $gutters / $columns;
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto; // IE10 doesn't support calc() here
box-sizing:border-box; // so you can freely apply borders/paddings to items
width: calc( #{$base_width}% - #{$gutter_offset} );
// remove useless margins (for cascading breakponts)
&:nth-child(#{$columns}n){
margin-right: 0;
}
// apply margin
@for $i from 0 through ($gutters){
@if($i != 0){
&:nth-child(#{$columns}n+#{$i}){
margin-right: $gutter_width;
}
}
}
}
Usage:
ul{
// just this:
@include flexbox_grid(3,20px);
}
// and maybe in following breakpoints,
// where the container is already setted up,
// just change only the cells:
li{
@include flexbox_cell(4,40px);
}
Obviously, it's up to you to eventually set container's padding/margin/width and cell's bottom margins and the like.
Hope it helps!
I modified the example presented by Dan Andreasson by using a right border on elements to create a faux gutter. You can then use nth-child to remove the border on the last-child of the column grid count you need. here is a demo https://codepen.io/JacobLett/pen/mdVoroM
/* demo only */
body {
margin:0;
padding:0;
max-width:1024px;
margin:0 auto;
}
.block-list {
background: #ccc;
border:1px solid #ccc;
}
.block-list .block-list__item {
background: #eee;
}
/* demo only */
.block-list .block-list__item {
min-height: 100px;
margin-bottom: 1rem;
}
@media only screen and (min-width: 900px) {
.block-list {
display: -webkit-box;
display: flex;
flex-wrap: wrap;
-webkit-box-pack: justify;
justify-content: space-between;
background-color: #ffffff;
margin: 1em auto;
}
.block-list:after {
content: "";
-webkit-box-flex: 1;
flex: auto;
}
.block-list__item {
height: 10em;
width: 25%;
box-sizing: border-box;
border-right: 10px solid white;
}
.block-list-2 .block-list__item {
width: 50%;
}
.block-list-2 .block-list__item:nth-child(2n) {
border: none;
}
.block-list-3 .block-list__item {
width: 33.3%;
}
.block-list-3 .block-list__item:nth-child(3n) {
border: none;
}
.block-list-4 .block-list__item {
width: 25%;
}
.block-list-4 .block-list__item:nth-child(4n) {
border: none;
}
.block-list-5 .block-list__item {
width: 20%;
}
.block-list-5 .block-list__item:nth-child(5n) {
border: none;
}
.block-list-6 .block-list__item {
width: 16.66%;
}
.block-list-6 .block-list__item:nth-child(6n) {
border: none;
}
}
<h2>2 column</h2>
<div class="block-list block-list-2">
<div class="block-list__item">1
</div>
<div class="block-list__item">2
</div>
<div class="block-list__item">3
</div>
<div class="block-list__item">4
</div>
<div class="block-list__item">5
</div>
<div class="block-list__item">6
</div>
</div>
<h2>3 column</h2>
<div class="block-list block-list-3">
<div class="block-list__item">1
</div>
<div class="block-list__item">2
</div>
<div class="block-list__item">3
</div>
<div class="block-list__item">4
</div>
<div class="block-list__item">5
</div>
<div class="block-list__item">6
</div>
</div>
<h2>4 column</h2>
<div class="block-list block-list-4">
<div class="block-list__item">1
</div>
<div class="block-list__item">2
</div>
<div class="block-list__item">3
</div>
<div class="block-list__item">4
</div>
<div class="block-list__item">5
</div>
<div class="block-list__item">6
</div>
</div>
<h2>5 column</h2>
<div class="block-list block-list-5">
<div class="block-list__item">1
</div>
<div class="block-list__item">2
</div>
<div class="block-list__item">3
</div>
<div class="block-list__item">4
</div>
<div class="block-list__item">5
</div>
<div class="block-list__item">6
</div>
</div>
<h2>6 column</h2>
<div class="block-list block-list-6">
<div class="block-list__item">1
</div>
<div class="block-list__item">2
</div>
<div class="block-list__item">3
</div>
<div class="block-list__item">4
</div>
<div class="block-list__item">5
</div>
<div class="block-list__item">6
</div>
</div>
Without any extra markup, just adding ::after
worked for me specifying the width of the column.
.grid {
display:flex;
justify-content:space-between;
flex-wrap:wrap;
}
.grid::after{
content: '';
width: 10em // Same width of .grid__element
}
.grid__element{
width:10em;
}
With the HTML like this:
<div class=grid">
<div class="grid__element"></div>
<div class="grid__element"></div>
<div class="grid__element"></div>
</div>
If you want a grid with some space between the items and the items starting without any initial space then this simple solution works:
.grid {
display: flex;
flex-flow: row wrap;
margin: 0 -5px; // remove the inital 5px space
width: auto;
}
.grid__item {
width: 25%;
padding: 0 5px; // should be same as the negative margin above.
}
If you want the initial 5px space then just remove the negative margin :) Simple.
https://jsfiddle.net/b97ewrno/2/
The accepted answer, whilst good, it causes there to be no space between the elements on the second row..