DEV Community

loading...
Cover image for CSS Patterns — Deep dive in grids

CSS Patterns — Deep dive in grids

xowap profile image Rémy 🤖 ・6 min read

Over recent years, CSS grids became one of the main way to deal with layout. And for good reason: they will manage both your margins and automatically stack up content when in mobile mode. As a matter of fact, grids are one of the main component of CSS frameworks like Bootstrap and a lot of designers will lay 12-column grid guides over their designs.

However, after working on many pixel-perfect integrations and layouts, I've come to realize that grids are a concept very easily setup and configured to match your custom requirements.

The goal of this article is to dive into how grids work and how you can use them in your layouts. In substance, you'll learn that it takes very little effort to build your custom grid system.

What is a grid?

The Grid. The digital frontier. I tried to picture clusters of information as they moved through the computer. What do they look like? Ships? Motorcycles? Were the circuits like freeways?

Woops. Wrong grid.

So here we're (unfortunately) not talking about the Grid from Tron. We're also not talking about the actual CSS grid feature because its support does not cover IE 11 and a lot of us still need to deal with it. Although the applications are the same — the native grid being more powerful, of course — we're going to explain the workings of old-school, à la Bootstrap grids.

The idea behind grids is fairly simple. Consider that your content fits into boxes, then you can create a grid on your page and fill each cell of the grid with one of those boxes.

The above example is a very simple form of grid: just images all of the same size, flowing in the page and wrapping to the next line when the page is too narrow.

You can start seeing that while the content size stays the same, if the screen size then the content reorganizes itself to fit the screen width.

In short, a grid is a way to flow your content that is automatically responsive.

Down the gutter

Next thing you want in a grid is to avoid getting everything sticking together. Indeed, in the previous example we're seeing all those pictures touching each other but in real life you usually expect to see a gutter between your content cells.

Let's try to set a margin to each cell with:

@gutter-size: 20px;

.cell {
  padding: @gutter-size 0 0 @gutter-size;
}

As you can see, a gutter forms but it also forms between the grid container and the cells. You can think of different tricks to counteract this but mostly you're going to run into various issues with the first row or the last row or alignment problems.

Now, what if instead of puting the whole gutter on top, half of the gutter was on top and half of the gutter was on the buttom? And same thing for the left/right gutter?

@gutter-size: 20px;

.cell {
  padding: (@gutter-size / 2);
}

Now you'll tell me: "but Rémy, you did only shift the cells, you didn't remove the gutter between the cells and the container. You are useless and I'll stop reading right now!"

This is however just a first step! Because we're "radiating" margin in all directions, it becomes very easy to offset with a negative margin on the grid.

@gutter-size: 20px;

.grid {
  margin: -(@gutter-size / 2);
}

And boom, the images are perfectly aligned with the container while retaining their gutter.

Cell structure

At this point it's interesting to mention the way cells are made in HTML:

    <div class="cell">
      <div class="inside"></div>
    </div>

The cell itself contains the gutter, so it's not really an element onto which you want to apply any other style.

What is really going to be the visual cell is the inside element, on which you can apply all the style (borders, backgrounds, internal paddings and otherwise).

Sizing items

In the previous examples, the grid items had a fixed size. But what if you want each cell to be a relative size?

You might have noticed in the previous section that we're using padding instead of margin. The reason is that this simplifies a lot size computation when it comes down to relative sizes.

If you want to make a grid where all items take up 1/4 of the width, it's as simple as:

.cell {
  box-sizing: border-box;
  width: 25%;
}

In the following example, we've got:

  • Blue boxes which are the content boxes of random height
  • Grey boxes are the cells
  • Red border is the container delimitation

The great advantage of doing the grids yourself is that you can invent things that are not strictly sticking to the 12-columns grid scheme. By example, using flexboxes, you can do a cell size that fills up remaining space by creating a flex-based sizing system.

.s10p {
  flex: 0 0 10%;
}

.s20p {
  flex: 0 0 20%;
}

.sfill {
  flex: 1 1 100%;
}

Let's note that here the .sfill sizing works only because the flex doesn't wrap. If you need this feature you cannot have a wrapping grid.

Without flexboxes

Previous layouts work using flexboxes, which are not necessarily available on your platform. So you might need to go really old school on this one!

No problem, let's use inline-block display!

Note — If you're doing this, you need to make sure that your HTML code has no whitespace between grid cells, otherwise it'll create small spaces between blocks and you definitely do not want that

@gutter-size: 20px;

.grid {
  margin: -(@gutter-size / 2);
  line-height: 0;
}

.cell {
  padding: (@gutter-size / 2);
  display: inline-block;
  vertical-align: top;
  box-sizing: border-box;
}

.s40p {
  width: 40%;
}

.s60p {
  width: 60%;
}

Admittedly this isn't the most convenient but it works fine enough!

Stacking

One of the main advantages of grids is the ability to stack items when the screen size requires it. Depending on the technique you're using (flexboxes or inline blocks) it's as simple as setting the width of all cells to 100%:

@media (max-width: 1000px) {
  .cell {
    // For flexboxes
    flex: 0 0 100%;
    // For inline blocks
    width: 100%;
  }
}

Please note that doing so with flexboxes will require flex-wrap: wrap, otherwise everything will stay on the same line.

Another option with flexboxes, especially if you didn't enable wrap, is to flip the flex direction.

@media (max-width: 1000px) {
  .grid {
    flex-direction: column;
  }

  .cell {
    width: 100%;
  }
}

In those examples, you can see how the stacking happens very naturally thanks to the gutter technique.

When to use

I cannot stress enough the fact that I'm using those custom grids all the time and I never use framework grids anymore.

The reason is that custom grids are so simple to make yet behave exactly like you need. Generic grid systems are tied to the framework you're using, their compatibility target and other elements which might not play in your interest.

As the gutter system is so powerful, I use these kinds of systems litteraly all the time, even sometimes just to stack up elements!

Wrapping up

If you need to create your grid system, you first need to consider what underlying technique you're going to use:

  • Flexboxes are going to be simpler and more powerful
  • Inline blocks work on the most antiquated platforms you need to support

Then determine how is the sizing going to work. If you want the ability to have cells that fill up remaining space, you need to disable flex wrapping, which is going to affect the way you stack things.

And finally determine what kind of utility classes you are going to do. As I always do very ad-hoc grid systems, I usually don't do something too complicated. By example if I need only two sizes of cell, I'd create a cell-small and cell-big size class and that's it.

To go further with this, next time that you see in a project something grid-like don't hesitate to start asking yourself what kind of custom grid you can build for this using what is described here and then write the few CSS lines that you need for it. All you need to do is to superpose CSS codes from this article:

  • Gutter management
  • Cells sizing
  • Stacking
  • Flexbox/Inline block

Don't hesitate to ask for help in the comments, in case things are not entirely clear!

Discussion (0)

Forem Open with the Forem app