Creating a Lightweight Grid System

When it comes to the struc­ture of a web­site, the first thing I like to sort out is the under­ly­ing grid sys­tem. There are a large num­ber of avail­able grid sys­tems out there, but not many that are respons­ive (prefer­ably mobile-first) and nestable while remain­ing extremely light­weight.

With this in mind I set out to cre­ate a fairly simple grid sys­tem that would be suit­able for the major­ity of my pro­jects while also meet­ing the above require­ments. The fin­ished product weighs in at 0.805 kb (less than 30 lines of code) while being both mobile-first and nestable. Here it is in all its glory:

Let’s look at exactly what it is I’m doing with each part of the above code.

@media (min-width: 40em) { ... }

As this grid sys­tem is mobile-first, I want the block-level ele­ments I’m using for the grid to take up their nat­ur­al width (100%) on nar­row devices. I’ve there­fore wrapped the whole lot in a media query. This means that the grid won’t kick in until the view­port is at least 40em wide. Keep in mind that the width that the grid should start work­ing at depends on the con­tent; 40em is just a rough guide. I chose not to use any addi­tion­al media quer­ies as they are tied dir­ectly to the con­tent. Most pro­jects should work with a single break­point but if you need more then make sure to add them.

.grid {
margin: 0 -0.75em;
}

The .grid ele­ment is giv­en neg­at­ive left and right mar­gin to account for the left and right pad­ding each of the columns are giv­en (i.e. the column’s gut­ter). That way, when using the grid as part of a page, it will still appear as wide as the oth­er block-level ele­ments above and below. I’m basing the gut­ter width on the stand­ard baseline height that I use for most pro­jects (1.5em), but feel free to adjust this to suit your indi­vidu­al needs.

The columns them­selves sit side-by-side with the use of inline-block. See this art­icle to learn why I prefer to use inline-block as opposed to floats when lay­ing out a web­site. I am using box-sizing: border-box; to ensure that the pad­ding is con­tained with­in the column’s width.

It is well known that using inline-block renders the white space between inline-block ele­ments. There are a few ways to handle this, but the most reli­able is to com­ment out the white space between inline-block ele­ments in the markup. Here is an example of what I’m talk­ing about:

Now, in terms of nest­ing, the only thing I need to take care of is any unwanted pad­ding and mar­gin. This is pretty easy; I simply remove the mar­gin and pad­ding from any column that also has a class of grid.

Rather than use an altern­at­ive nam­ing sys­tem for column widths I decided to use the exact per­cent­age value. I feel that this makes it easi­er to use over­all as there is no learn­ing curve. I’m also using BEM syn­tax, and for those that are unfa­mil­i­ar with what that is, check out this art­icle.

Finally, I’ve also con­ver­ted the grid sys­tem from CSS to SCSS. That code can be found here.

Great piece. I’ve nev­er been sold on grids, mainly because of the lack of mobile first point you made. I’ve seen a few bad imple­ment­a­tions that have put me off. This how­ever has got me inter­ested again. Thanks!

this looks awe­some. I have to give this a try. Much bet­ter for smal­ler sites than a bloated frame­work like Bootstrap or Foundation. Earlier this year, I’ve come across a simple grid solu­tion cre­ated by David Bushell, but yours seems even more light­weight. Great work!

until flexbox will be widely sup­por­ted, i’m a great fan of using inline blocks over float­ing ele­ments in lay­outs. as you’ve men­tioned the notori­ous white space issue, i’ve come up with anoth­er approach to tackle it: http://jsfiddle.net/ipaas/H69aZ/2/

i’m using rem-units to reset the con­tain­ing ele­ments’ font-size instead of pixels to reflect root element’s dif­fer­ent font size across medi­aquer­ies. leg­acy ie’s would require either a poly­fill or a sim­pler tar­geted pixel val­ues set.

Andrew, if you want to add that func­tion­al­ity then I would sug­gest mov­ing my code out­side of the media query and then using a ‘full width’ class and a max-width media query to select­ively enforce respons­ive columns.