Grids are a major part of web design today. There are plenty of frameworks out there that bundle in robust grid systems that can do a lot but are sometimes not very flexible. Many times we just need something really simple, without all the baggage that comes with a framework.
Negative margins
This is a little trick to use some negative margins and percentage based widths (and margins) to get a nice clean grid. It’s useful for a simple image gallery or possibly some sort of grid navigation.
We’ll start with some simple HTML.
1
2
3
4
5
6
7
8
9
For the CSS, I am using SASS because I want to take advantage of mixins, variables and math to make things easy for me.
@mixin break($query) {
@media screen and (min-width: $query) {
@content;
}
}
$gridMargin: 1%;
.page {
position: relative;
max-width: 1000px;
margin: 0 auto;
}
header {
background: gray;
height: 50px;
margin-bottom: $gridMargin;
}
.grid__wrapper {
width: 100%;
@include break(500px) {
/* extra width and negative margins to make sure we are flush with the left and right sides */
width: 100% + ($gridMargin * 2);
margin-left: -$gridMargin;
}
}
.grid__item {
box-sizing: border-box;
background: pink;
padding: 16px;
margin: 0 0 $gridMargin;
@include break(500px) {
float: left;
margin: $gridMargin;
width: 50% - ($gridMargin * 2); // 50% - 2% of margin
/* clear the left column floats in case content changes height */
&:nth-child(2n-1) {
clear: left;
}
}
@include break(800px) {
width: 33.33% - ($gridMargin * 2); // 33.33% - 2% of margin
/* reset nth-child from previous media query */
&:nth-child(2n-1) {
clear: none;
}
/* clear the left column floats in case content changes height */
&:nth-child(3n-2) {
clear: left;
}
}
}
FlexBox
Flexbox is pretty amazing. We can achieve the same results as above (better, really) with less code. The support for flexbox might make it a non-option for many projects but most modern browsers support it and it can be used pretty safely today. We’ll use the same HTML as above. And the SCSS below.
@mixin break($query) {
@media screen and (min-width: $query) {
@content;
}
}
$gridMargin: 1%;
.page {
position: relative;
max-width: 1000px;
margin: 0 auto;
}
header {
background: gray;
height: 50px;
margin-bottom: $gridMargin;
}
.grid__wrapper {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.grid__item {
box-sizing: border-box;
width: 100%;
background: pink;
margin: 0 0 $gridMargin;
padding: 16px;
@include break(500px) {
/* 2column - width minus half the grid margin - we're trying to get as close to 50% minus the gridMargin (in between the 2 columns) */
width: 50% - ($gridMargin/2);
}
@include break(800px) {
/* 3column - width minus half the grid margin - we're trying to get as close to 33.33% minus the gridMargin (in between the 3 columns) */
width: 33.33% - ($gridMargin/1.5);
}
}