Grids without troubles

Original author: Chris Coyier
  • Transfer
The vast majority of sites are created using grid layouts. They may not use them explicitly, but if the site has a block with the main content located on the right and a side block (sidebar) located on the left, then this is the simplest grid.

If you need to implement more complex grids, then people resort to using frameworks. They believe that grids are an overly complex thing that is best left to true CSS experts. Confidence in this is reinforced by the fact that most of the grid frameworks they deal with are very complex.

In this article, I will tell you how I layout a grid layout. It is not so difficult. And even to make rubber nets is not difficult.

Wrapper


The width of the column wrapper is equal to the width of its parent. We can take its width as 100%. Since the wrapper has no semantic meaning, we will use a simple div for it.
<div class="grid">
  <!-- 100% wide -->
</div>



Speakers


Let's start with a layout that is often used in practice, consisting of: an area with main content 2/3 wide and a side block 1/3 wide (from the parent's width). To do this, we will create two divs with the corresponding classes:
<div class="grid">
  <div class="col-2-3">
     Main Content
  </div>
  <div class="col-1-3">
     Sidebar
  </div>
</div>


To place them next to each other, we set the float property for them and set the width. Float can be set to multiple columns at once like this:
[class*='col-'] {
  float: left;
}

and the width is set individually:
.col-2-3 {
  width: 66.66%;
}
.col-1-3 {
  width: 33.33%;
}


That's the whole premise for grids without troubles.

Stream cleaning


Since our wrapper contains only floating elements (columns with the float property set), its height collapses to zero (because floating elements do not affect the size of the parent - approx. Per.) . To fix this, you need to clear the stream. For now, just add this:
.grid:after {
  content: "";
  display: table;
  clear: both;
}


Indent between columns


Indentation between columns is the hardest part of a grid layout. We have already made our grid “rubber” by setting the column width as a percentage. Now we could complicate everything with mathematical calculations and set the width in percent and for indents between columns. Personally, I am not a supporter of such methods; I prefer setting fixed indents between columns. And, besides, in this article we try not to bother much.

As a first step, we will use the box-sizing property with the value of border-box. I like to apply it to all elements at once.
*, *:after, *:before {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}


Now neither indents nor borders will affect the sizes of elements.

As a second step, we set a fixed indent on the right side to all columns except the very last one.
[class*='col-'] {
  padding-right: 20px;
}
[class*='col-']:last-of-type {
  padding-right: 0;
}


That's all for indentation between columns in the simplest case.

Indentation


Need external padding between columns? I use an extra class for this:
<div class="grid grid-pad">
  Сетка с внешними отступами
</div>


First of all, we add the left indentation to the column wrapper (as well as the upper and lower indentation at your discretion):
.grid-pad {
  padding: 20px 0 20px 20px;
}


Then we will return the right margin to the last column:
.grid-pad > [class*='col-']:last-of-type {
  padding-right: 20px;
}



More different columns


It is very simple:
.col-1-2 {
  width: 50%;
}
.col-1-4 {
  width: 25%;
}
.col-1-8 {
  width: 12.5%;
}

You can do anything with them. Just do not forget that the sum of fractions should not exceed one. To do this, have to brainwash, but there is nothing complicated.


Sass


I don't use it often, but all of our code is becoming more compact thanks to SCSS / Compass:
* {
  @include box-sizing(border-box);
}

$pad: 20px;

.grid {
  background: white;
  margin: 0 0 $pad 0;
  
  &:after {
    /* Or @extend clearfix */
    content: "";
    display: table;
    clear: both;
  }
}

[class*='col-'] {
  float: left;
  padding-right: $pad;
  .grid &:last-of-type {
    padding-right: 0;
  }
}
.col-2-3 {
  width: 66.66%;
}
.col-1-3 {
  width: 33.33%;
}
.col-1-2 {
  width: 50%;
}
.col-1-4 {
  width: 25%;
}
.col-1-8 {
  width: 12.5%;
}

/* Opt-in outside padding */
.grid-pad {
  padding: $pad 0 $pad $pad;
  [class*='col-']:last-of-type {
    padding-right: $pad;
  }
}


Modules


When working with such grids, I like to use “modules”.
<div class="grid">
  <div class="col-2-3">
     <article class="module">
        stuff
     </article>
     <article class="module">
        stuff
     </article>
  </div>
  <div class="col-1-3">
    <aside class="module">
       Sidebar stuff. Sub modules?
    </aside>
  </div>
</div>


It is very convenient to break content into such pieces. An additional benefit of them is that each module can be indented to separate text from the edges of columns.

Result


A demonstration of the result can be found here .

Showdowns with browsers


The code works fine in IE 9 version and above, as well as in all other browsers. If you need IE7, then do something else.

(It should be noted that in Opera, support for fractional percentages appeared only in version 12. - approx. Per.)
By the way, the model of “flexible blocks” (flexbox, flexible box) in the future will simplify the implementation of grid layouts and even improve it (by a variety of way, including the ability to rebuild the columns on demand). But I think that it will take us about another year to begin to at least think about using “flexible blocks”.

Related Information


Take a look at the grids from the OOCSS framework .

Solution for IE8 (add-on by translator)


In the original article, the author pointed out that this method works fine in Internet Explorer 8 version. But he was wrong, because IE8 does not support the pseudo-class: last-of-type. But he supports the pseudo-class: first-child which will help us solve this problem.

In CSS we change: last-of-type to: first-child and instead of right indentation at the columns we set left:
[class*='col-'] {
  padding-left: 20px;
}
[class*='col-']:first-child {
  padding-left: 0;
}

And in the same way, edit the code for the indentation:
.grid-pad {
  padding: 20px 20px 20px 0;
}
.grid-pad > [class*='col-']:first-child {
  padding-left: 20px;
}