Over the past few years CSS grid systems have grown a lot in popularity, quickly becoming considered best practice for rapid layout scaffolding. As a result, there has been no shortage of frameworks popping up offering their own grid systems trying to garner favor.

If you’re the curious type, such as myself, than you may be asking yourself what exactly grid systems bring to the table? How do they work? And how might you go about creating your own? These are just some of the questions I will be trying to answer as I explore the various concepts at play while stitching together a basic grid system from the ground up.

What is a Grid System?

In case you’re new to CSS grid systems, we’ll start with a quick definition. In basic terms, a grid system is a structure that allows for content to be stacked both vertically and horizontally in a consistent and easily manageable fashion. Additionally, grid system code is project-agnostic giving it a high degree of portability so that it may be adopted on new projects.

The Benefits

  • They increase productivity by providing simple and predictable layout scaffolding to HTML design. The structure of a page can be formulated quickly without second guessing its precision or cross-browser compatibility.
  • They are versatile in how layouts can be constructed, being adaptable in varying combinations of rows and columns. They even support nested grids for more complex use cases. No matter your layout requirements, a grid system is almost certainly well suited.
  • They are ideal for responsive layouts. This is where grid systems reign supreme. They make it incredibly easy to create mobile friendly interfaces that are adaptable to different sized viewports.

The Primary Components

Grid systems include two key components: rows and columns. Rows are used to accommodate the columns. Columns make up the final structure and contain the actual content. Some grid systems will additionally include containers, which serve as wrappers for the layout.

Resetting the Box Model

First and foremost, it is important for any grid system to reset the box model. By default, the browser does not include the padding and border within the declared width and height of an element. This does not bode well for responsiveness. Thankfully, this can be fixed by setting the box-sizing property to border-box for both rows and columns:

.row, 
.column {
    box-sizing: border-box;
}

Now we can leverage percentages for the widths of the columns. This allows the columns to scale upwards and downwards within different viewports while maintaining the structure.

Clearing Floats

In order to align the columns horizontally, grid systems will float the columns. This means you need to clear the floating elements on the row to maintain the structure of the layout. This is where a clearfix comes in:

.row:before,
.row:after {
    content: " ";
    display: table;
}

.row:after {
    clear: both;
}

By applying the clearfix to the row in your CSS, it will cause the row to stretch to accommodate the columns it contains without adding to the markup.

Defining Columns

For columns, the styles need to be defined in 2 parts: the common styles and the widths. First the common:

.column {
    position: relative;
    float: left;
}

Here, the column is given a relative position to allow any absolutely position content within the column to be positioned relative to that column. The column is then floated left for horizontal alignment, which will cause the element to become display: block even if it did not start out that way.

Creating Gutters

Gutters help to create separation between columns for greater legibility and aesthetics. There are 2 schools of thought when approaching gutters; defining paddings within each column or using a percentage-based left margin for each column.

I prefer the latter approach because it facilitates responsive gutters that will remain relative to the columns and the viewport as a whole with different screen sizes. It also lets you define additional paddings for columns for further flexibility. The biggest advantage of padding-based gutters is in how they simplify calculations for column widths, which will become evident in the next section.

Using the percentage-based margin approach, we can target columns that are an adjacent sibling to a preceding column. This will create a left margin for every column except the first one, which we’ll define at 1.6% using the margin-left property:

.column + .column {
    margin-left: 1.6%;
}

Calculating Column Widths

Before we can begin making calculations, we need to determine the maximum amount of columns per row. A popular choice is 12 as it boasts flexibility given that it is divisible by 1, 2, 3, 4, and 6. This permits a variety of different combinations that still allow for evenly distributed columns of the same size.

It’s important to understand that by going with a maximum of 12 columns per row, you need to fulfill that amount for every row regardless of how many columns you want. For example, if you wanted only a row of 3 equal columns, you would use 3 elements that each span 4 columns (4×3=12). Exceeding the sum of 12 will result in the extra column(s) wrapping to a new line.

Now that we know the maximum number of columns, next we need to determine the width of a single (1/12) column using the following formula:

scw = (100 – (m * (mc – 1))) / mc

Where:

  • scw = single column width
  • m = margin (1.6%)
  • mc = maximum columns (12)

When we plug in the numbers, we get a single column width of 6.86666666667%. From here we can use this number to calculate the rest of the column widths. The formula for this is:

cw = (scw * cs) + (m * (cs – 1))

Where:

  • cw = column width
  • scw = single column width (6.86666666667%)
  • cs = column span (1-12)
  • m = margin (1.6%)

Applying this formula for each of the 12 columns results in the following CSS.

.column-1 {
    width: 6.86666666667%;
}

.column-2 {
    width: 15.3333333333%;
}

.column-3 {
    width: 23.8%;
}

.column-4 {
    width: 32.2666666667%;
}

.column-5 {
    width: 40.7333333333%;
}

.column-6 {
    width: 49.2%;
}

.column-7 {
    width: 57.6666666667%;
}

.column-8 {
    width: 66.1333333333%;
}

.column-9 {
    width: 74.6%;
}

.column-10 {
    width: 83.0666666667%;
}

.column-11 {
    width: 91.5333333333%;
}

.column-12 {
    width: 100%;
}

Optimizing for Mobile Devices

Despite the fact that the grid system is responsive, it can only go so far. For devices with small viewports, such as smartphones, the width of the columns need to be adjusted to allow the content they contain to still appear legible and visually appealing. Media queries help with this:

@media only screen and (max-width: 550px) {
    .column-1, 
    .column-2, 
    .column-3, 
    .column-4, 
    .column-5, 
    .column-6, 
    .column-7, 
    .column-8, 
    .column-9, 
    .column-10, 
    .column-11, 
    .column-12 {
        width: auto;
        float: none;
    }

    .column + .column {
        margin-left: 0;
    }
}

Here, we are telling the grid to allow every column to take up the full width of its container for devices with a viewport smaller than 550px pixels wide. Since gutters are no longer necessary here, we remove those too.

Alternatively, you could opt for a mobile first strategy that takes the opposite approach, scaling upwards to a 12-column layout. In such a case, columns start as full-width, then we establish the column widths and floats to allow them to align horizontally as the screen resolution reaches a specified threshold. This is the preferred approach for Bootstrap’s grid system, which doesn’t institute the column widths until the viewport reaches a minimum width of 992 pixels. This may be a more favorable approach for your use case, and should be something to look out for when evaluating a grid system.

Pulling it all Together

When we combine all the concepts and CSS, we can write HTML layout scaffolding like so:

<div class="row">
    <div class="column column-4"></div>
    <div class="column column-4"></div>
    <div class="column column-4"></div>
</div>

<div class="row">
    <div class="column column-2"></div>
    <div class="column column-4"></div>
    <div class="column column-4"></div>
    <div class="column column-2"></div>
</div>

Check out the CodePen demo below to see the entire grid system in action, including nested grids:

See the Pen Understanding CSS Grid Systems by SitePoint (@SitePoint) on CodePen.

You can also try the full screen demo for a better impression. Don’t forget to play around with the screen dimensions to see how the grid handles different viewports.

Conclusion

As you can see, it doesn’t take much to put together a basic grid system. The math is probably the most complex part. Despite its simplicity, the grid continues to be a powerful and flexible tool for layout scaffolding. With the various concepts I’ve discussed here, hopefully you have a better understanding of how grid systems work. This should help you evaluate different grid systems moving forward, and choose the right one for your next project, or even create your own.

Tags: css grid, css grid system, grid system
Web developer based in Barrie, Ontario, Canada with a real passion for everything front-end, especially JavaScript. I am a very proud Canadian, and yes, I love hockey, the stereotype is true! I blog about front-end web development at ryanmorr.com.
Comments
RyanReese

How do your column width calculations arrive at a different point than frameworks like Foundation and Bootstrap. What I mean is, why do they evenly divide the width (100%/12) while you do not? Eh, I mean what benefits does that bring over Foundation/Bootstraps way? What makes your way better than theirs?

I'm just trying to follow along. I understand your calculations but I'm just curious why you decided to not follow that evenly divided route. Is this just a case of ToMAtoe Tomatoe?

RyanMorr

The columns do in fact add up to a width of 100% when combined with the percentage-based left margin for each column except the first one to form the gutters. Hence the complicated calculations.

The difference with Bootstrap is that it sets a zero margin on the columns, and instead sets a padding on each column to form the gutters. This simplifies the calculations with (100%/12) as you noted.

They are two different approaches for creating gutters with slight differences. It's merely a matter of preference.

Hope this helps.

RyanReese

Perfect. Thanks.

chronicler_isiah

Nice article. A fairly complex set of ideas simply explained.

Cheers

Tarabass

The biggest concern with css frameworks is that we now have to explain this kind of basic css rules. For every frontend developer out there it should not be any question how this grid systems are written and how they work. If you don't know this you should not be using frameworks like this. As you can see in this article it is very simple explaining how grid systems work and it is not of any use to explain it at all. If you read something new in this article you should consider learning css and not trying to understand how css frameworks work..

Pal_Tamas

That was a pretty stupid comment. You say as if it was rocket science, css can be learned over a weekend.

RyanReese

I can learn any language in a weekend. Anyone can.

Can you learn the most advanced features of any language in a weekend? No. Yours was just as unthoughtful as the above posters was.

Tarabass

I don't say CSS is rocket science, and learning CSS looks easy. But CSS has a lot of unpredictable pitfalls. Pitfalls you only know if you are experienced with lots of code and big enterprise software used across all browsers and platforms. I can show you tons of CSS from which you can hardly tell what would be the outcome. For example, did you know CSS isn't truly cascading?

But my point was that you should know the basics before you start with frameworks like this. And if you know the basics their is no need to explain grid systems. And if you don't understand grid systems, you should not try to understand them but learn the basics. So if this article was useful for you, go and learn the basics of CSS. Again, their should not be any need to write articles about grid systems..

RyanMorr

I think there is no prescribed way to learning a subject. Who cares how you came to learn something, as long as you did learn something.

Tarabass

Because you don't want to learn how they did it, but why they did it this way.

RyanReese

Why? Are there studies showing the best way to learn something? Or is this purely your opinion based off no sound facts or information that can be proven.

I constantly see people come in here who know certain parts of CSS but not others. Do I agree with that? Doesn't matter to me. I see those same people come back here months or years later and they all are great developers now.

RyanMorr

I look at it in terms of exposure. I read something and maybe I see something I've never seen before. From there I do my research to learn about it. But if not for that first article, I would not have been exposed to it. The only thing worse that not knowing something is not knowing about what you don't know. I view anything that exposes me to something new as beneficial, now matter how I got there.

I largely taught myself JavaScript by looking at various libraries and frameworks that would employ advanced design patterns that were way over my head. I can still vividly remember the day I first learned about the call and apply methods of functions simply looking through the source code of ExtJS. Did I learn anything from ExtJS about call and apply... no, but it did expose me to them.

Tarabass

This doesn't apply to all program languages? The need of knowing why they do it in a way, and not how they do it? I've seen to much copy cats and programmers who do a trick over and over but have no idea what they are doing. This can lead to very odd situations where somebody with knowledge can't understand what is happening.

And sure, it is my personal opinion. But it is an opinion based on years of experience working in big and small teams for big and small businesses. My opinion is that you can explain every rule of code you write, otherwise you shouldn't write them at all..

webZplus

Everyone comes to the first day of a new subject on a different day, we are not already born with the knowledge of CSS Frameworks or Grid layouts (perhaps we should be) what I find interesting is how similar a css GRID is to the good old days of tables... table, tr, td etc... might have to change container, row and column just for old times... and find my faithful friend the 1 pixel transparent gif stuck_out_tongue_winking_eye

pwrmacbob

Speaking of tables... I'm a beginner, so no laughing. I can follow what is going on with the html and css of this article. I was wondering. What if one of the columns is used as a label on a form? I don't want the label in a "box" like the other columns. How would you differentiate the two columns?

RyanMorr

Let me see if I am understanding you correctly, you want to make a <label> element one column and another column that contains a field of some sort for a form? If so, you can make the label element itself a column by adding the appropriate classes. I'm not sure what you mean by differentiate the two columns? You can add a unique id or class name to target a specific column in JavaScript and CSS.

Michael_Morris

Not by a long shot actually. The biggest problem with CSS grid systems is they push layout rules back into the HTML where it doesn't belong. CSS was developed to get styling markup out of the HTML, putting it back in via classes is a bit wrong headed. But then there's the pragmatic side of the coin - it does save a lot of time despite not being ideal.

Also, note the following:

div:after

is wrong. it's

div::after

The single colon implementation works on IE 8 and the other browsers tolerate it, but the markup is incorrect all the same. Also, floating things around is far less useful than using a proper flexbox model. IE 9 and 10 have a smaller market share than 8 in many areas, so skipping them as well is becoming an option thank goodness.

pulpybucket

Hi, See the website http://www.localjobpool.com
I would like to hide the green top bar in mobi
le view.
Staring code of div tag is:

<div id="info">
<div class="menuHolder">
<ul class="nav">
....
....
</div>

menuHolder and nav are defined in my custom CSS. I tried the solution like
@media screen......

like 

@media screen and (max-width: 500px) {
.info .menuHolder .nav {
display: none
}

}

Please tell me how I can hide this bar in mobile view. And where should I insert the code suggested by you...

RyanReese

LOok at your div id="info element. Then look how you are calling it in your CSS.

.info .menuHolder .nav

anthorr

First off, great article. As for the "CSS in a weekend" comment: learning the correct syntax for a language and knowing how to make it sing are two different things. You can learn the correct syntax for CSS, but that doesn't mean you know it. I've been playing around with it for a decade and am STILL fascinated by the things people do with it. As a backend/DB dev by trade and someone who is fluent in over a dozen different development languages and APIs, I can say that creating with CSS is by far the most personally satisfying work I do, as well as the most challenging. It isn't anything any code geek should be looking down their nose at.

jklepatch

Great article, thanks for this smile

As for the comment about css being so easy to learn that it can be done over a weekend, it really depends what do you mean by 'learning'. If you mean to be able to do something with it, sure, you can even create your first layout just after having studying css for a few hours.

Now, how about making it cross-browser compatible and responsives ?
How about smart layout that adapt to the content, and doesn't break as soon as the content is not exactly 'ideal' for your layout ?
How about knowing exactly how to combine the different properties ?
Does width: 0 auto works to center horizontally a div without a fixed width ?
How does percentage actually work ? it's a percentage of what ?
How does background-position work ? does background-position: 25% 25% means the left and top edges of the image will start at 25% of the left and top edge of the div ? No it doesn't.

Knowing the details and how to combine css properties take time and is definetly not learned over a weekend.

RyanReese

Trick question; width:0 auto; is invalid (you meant margin wink ) and also what's the display type for the div wink .

PaulOB

It depends on your point of view.:)

It's perfectly valid in CSS 2.1 when used on the elements available in the css2.1 specs: namely, :first-line, :first-letter, :before and :after. If you are supporting IE8 then you must use the single colon syntax for the above elements.

If you use css3 the new pseudo elements (that weren't available in CSS2.1) then you should use the double colon syntax.

From the specs:

For compatibility with existing style sheets, user agents must also accept the previous one-colon notation for pseudo-elements introduced in CSS levels 1 and 2 (namely, :first-line, :first-letter, :before and :after).

Millions of pages were written using :after long before ::after came into being and they don't all suddenly become invalid smile

Michael_Morris

Useless pedantry. By the time IE 8 was built everyone else had already moved to the :: syntax. So at this point it's a way to reliably shut out Microsoft's crappy browser. No one has ever used :after or :before to insure it will continue to work on any browser but IE 8.

PaulOB

I beg your pardon? I take exception to that.

I was merely pointing out that :after is perfectly valid css 2.1 and there is no reason to use ::after as long as you are supporting IE8 (which quite a lot of us still do). Telling people to use the double colon syntax on CSS 2.1 pseudo elements will cause those pages to break in IE8 which is why I chimed in as you are not the first to recommend this.

The html5 boilerplate and bootstrap3 all use the single colon syntax for :after and :before and I recommend that everyone continues to use this format for a couple of more years at least.

jklepatch

Nice catch, you are right I meant 'margin' and not 'width' smile

About the display type, I was supposing a display: block;

Michael_Morris

Meh, the sooner IE 8 dies the better. And I'm not above putting in things I know will break in IE 8 these days when I'm allowed to.

Learn Coding Online
Learn Web Development

Start learning web development and design for free with SitePoint Premium!