CSS Grid — Simple Layout Tutorial

Here’s a list of my best web development tutorials.

Complete CSS flex tutorial on Hashnode.

Ultimate CSS grid tutorial on Hashnode.

Higher-order functions .map, .filter & .reduce on Hashnode.

Follow me @ Twitter, Instagram & fb to never miss premium articles.


A Blender render of a chess board on my Nvidia 1060 GTX. Having not much experience with chess, I swapped the knight and the bishop, by mistake.

In the spirit of creating article layouts for my own websites, in this write-up I will try to explain my thought-process behind replicating the Medium article scaffold, using only CSS grid.

We’re finally starting to see more people using the grid to create websites. A few different design patterns are emerging. One of them will be explained in this tutorial. But first, let’s take a look at the CSS grid box model…shall we?

Use the repeat property whenever possible. It shortens your CSS code.

In general, designing layouts with CSS grid isn’t easy for two reasons (especially if you’re trying to make a layout with it for the first time):

  1. The grid provides many different layout-creation properties at your disposal. What I found out is that you don’t have to use all of them. The grid doesn’t force you into a specific technique or design philosophy.
  2. Much like flex, CSS Grid is a complex HTML element. Grid-based layouts require one parent container and inner elements called items. Different CSS Grid properties affect both of them, separately. There are properties that are intended to work only to modify the parent container. Other properties work only on its items. Empty cells are part of the virtual grid scaffold. But they don’t actually contain any content.
  3. minmax, fr-units, and auto flow dense are not as trivial as some of the other CSS grid properties to understand (without taking an hour or two for visual experiments.) You can avoid media queries using them. But not always. (For example, switching fonts is still an issue that has little to do with scaling horizontal dimension of your site.) You can probably find a way around it by using scaling transforms or some sort. I still struggle with finding a balance between media queries and minmax in some cases.

Using the grid… designing layouts is all about planning space, columns, and rows. You have to think in multiple dimensions at the same time. Because you also have to worry about scaling your content across multiple resolutions.

How it’s done will depend on the type of the layout you will be creating. What will be your creative approach to making the best layout for the task at hand?

Hence, the first question you should ask is:

“What type of layout am I trying to create?”

A blog layout (which is primarily column-based) demands a different approach than an art gallery that would probably use square cells.

So what are we creating here?

This is a single CSS grid-based layout. Same code. No media queries.

Ironically I didn’t use minmax here either. I simply set max-width property on the main container via the good old style attribute.

Creating A Medium-like Article Publication Layout

Let’s recreate an article layout format similar to Medium. We will start by determining our main scaffold for the minimum content possible.

The Medium site has an interesting approach to spacing horizontal image content. It is a multi-lane design where you can extend the width of your image content to occupy different levels of wider space. Below is an actual screenshot of my first experiment making this layout using CSS grid:

To create the vertical slicing seen in this example, we can use fractional units or fr-units. Fractional units automatically determine the final pixel value of the lane, based on the size of all other columns combined. They help you make more abstract decisions about creating layouts.

For example: “This column should be about 3 times wider than the other one,” or “The border should be 5 times larger relative to what I consider 1fr.” Choosing these same proportions using pixels would be a productivity nightmare compared to CSS Grid’s elegant solution to this problem.

Following this intuitive logic, the 3 borders around the middle lane were created using 5fr, 3fr and 2fr. Whereas the middle lane is 700px.

Note: You can mix fr and pixel units. This means that 1 fr unit isn’t always the same in pixels. It is always relative to remaining space left after pixel based column width has been calculated. But fr units are always relative to themselves. Example: 5fr is always exactly 1fr x 5, whatever 1fr means in the context of your layout size.

CSS Grid Cuts Your Code In Half

To create this layout, all you need to do is supply the following commands to style your parent container:

display: grid;
grid-template-columns: 5fr 3fr 2fr 700px 2fr 3fr 5fr;
width: 1300px; /* Width is optional */

That’s all it takes. Rows can be specified respectively with the grid-template-rows property. But…in this case, we can safely rely on the grid’s cell content automatically expanding the height of each cell as it becomes necessary.

Cell Spanning

CSS grid supports spanning content across multiple numbers of cells. Because each grid cell correlates to a <div> element (inner item of the grid), when you span you will offset your entire HTML structure by the number of cells you span vertically or horizontally. This happens within the confines of your grid structure.

Here is an illustration of this concept:

To demonstrate how CSS grid spanning works, I made these diagrams. I created a minimalist layout with grid-template-column: repeat(7, 1fr).

<div style = "display: grid; grid-template-columns: repeat(7, 1fr)">
<div style = "grid-column: span 1">2</div>

In the first example, I set grid-column: span 1. But there is no change, because it matches the default behavior. Notice that because we have 7 placeholders in the grid but only 5 <div> elements, the grid will leave two empty spaces just at the end. Because the column scaffold is 7 blocks measured by 1fr units. Therefore, you see how the grid is really just a mental concept, rather than the actual rendering of the elements.

Let’s set the span of the 2nd item to 2:

Unlike <table>’s span, the grid will leave existing cells alone, rather than taking up their space. It will simply push the remaining <div> elements farther on the grid across its cell flow direction. Note that there is still one empty space remaining. Increasing the span to 3 takes care of that:

This is the case I wanted to talk about. When you design your primary grid scaffold, try to make sure that the number of <div> elements matches the grid template so that there are no empty spaces left.

Of course, this functionality exists for a reason. And it’s great for flex-like align on inner cells, especially when the number of items is unknown. But as far as primary scaffolds go (you know, the ones that encompass the outer skeleton of your entire site), I find that sticking to this rule is a good idea.

And finally, let’s see what happens if we span the cell too far. CSS grid will automatically create a second row. This is called an implicit row. It is created on demand, if the number of items is greater than the space defined by the grid-template-columns scaffold. Of course, you can create your own rows too and specify them explicitly, using sister property grid-template-rows. But we’re trying to stay minimalist here, for the sake of explaining the cell span example:

Here we see an implicit row (basically borrowing a copy of cell dimensions from the row prior to it) automatically created. Since we only have 5 divs, and one of them spans across 5 cells, CSS grid created 5 more empty spaces to fill in the last row. Note, these cells are actually not populated by any content. They are imaginary, until (and if) more <div>s are added to the HTML.

Dealing With Site Width And Centering

You may or may not want to specify width and margin: auto. If you do, your parent container will be centered to the middle of the screen and locked to the width. If not, your grid will automatically scale horizontally across the entire width of the browser / device you’re viewing it on.

In this example, I decided to lock width to about 1200px. Simply because in the age of 4K screens, the wider your layout becomes the more awkward it may start to look. Layouts that stick to some sort of a max-width value don’t lose anything even on extremely wide resolutions.

Good Code Is Simple — The HTML Scaffold

The CSS grid code in the very first example (header with multiple stages of width / created by 3, 5 and 7 cell spans) determines the column width of each <div> item in the parent container.

In the spirit of the Medium article layout, I used some abstract ideas when determining names for each stage of “wider” content:

Normal width is used for the primary body of text for the article.

Average width can be used to specify images that stick out of the sides of the main text, adding a touch of design to your one-column article.

Wider width is slightly more spacious. It can make larger, more important images stand out.

Widest (or full) width will occupy the entire width of the grid. This is reserved for the largest images. Perhaps some high resolution photography to create a more engaging experience for the readers.

I left HTML code as the last step. I just didn’t want to clutter this tutorial with it early on because after all… this is primarily a CSS grid discussion. But just to show you how easy it is to construct site layouts using the techniques explained above, your HTML will look close to this:

<div style = "display: grid;
grid-template-columns: 5fr 3fr 2fr 700px 2fr 3fr 5fr;
margin: auto;
position: relative;
width: 1300px;">
<!-- Primary header -- 7 columns//-->
<div><h1>Silver mist suffused the deck of the ship.</h1></div>
<!-- Sub-header -- 7 columns//-->
<div><h2>CSS Grid is here, but not many designers have fully grasped how to use it yet. As a tutorial writer, I constantly get asked questions about how the grid works.</h2></div>
<!-- Standard paragraph -- 7 columns//-->
<div>Hello there, this is a new paragraph.</div>
<!-- Average width -- 5 columns//-->
<div style = "grid-column: span 3;">Average.</div>
<!-- Wider width -- 3 columns//-->
<div style = "grid-column: span 5;">Wider.</div>
<!-- Full width (widest) -- 1 columns//-->
<div style = "grid-column: span 7;">Widest.</div>

There are no empty <div> elements or unused cells. The three <div>s in case of the most narrow column is a bit of an overhead. But it’s still a far cleaner solution in terms of flexibility. You can have 4-levels of content width.

By simply excluding the width property from parent container, you automatically get responsive borders. This is demonstrated in the following animation.

Minimalist Example

By rearranging the templates in the above HTML, it is possible to create a legitimate article layout. Here is the kind of article you can craft using this approach (I used the lorem ipsum text filler and some images):

Using wide space for responsive image content.

There are 3 borders on each side. They all have a function. Used together with the grid-rows: span x; value, you can limit the image to any of the 3 possibilities.

Simply rearrange the HTML blocks or add new ones whenever you need to use content. In the following example, I added a few more images. I also used different width spans to demonstrate versatility of this layout.

Going Mobile

All this is good. But what if we need to take this layout mobile? It is possible with a few modifications. Take a look at this 3-stage animation:

No media queries. No flex.

I’m not saying that flex is evil. Nor that this is the ideal way to design. It’s just one approach that works for this particular type of layouts. Think about this. The CSS grid minmax is really just a different manifestation of min-width and min-height from your standard set of CSS properties. It does give you a little edge, though, because minmax supports complex sets of values.

It’s difficult to demonstrate the changes a layout undergoes from full screen to the thin mobile resolution, because animating a browser’s width smoothly is time-consuming. So I used jQuery.animate method to the same effect.

  1. In first stage, we simply decrease the width of the entire grid to 800px.
  2. In second stage, we decrease the width again. This time to 400px. But… instead of using media queries to switch the actual grid-template-columns property to a new value of 0.7fr 0.5fr 0.1fr 20fr 0.1fr 0.5fr 0.7fr. (Here, for example, the middle column would be switched from 700px to 20fr, and the 3 borders would be set to much smaller fractional values to reduce the width of the mobile border), we can use minmax(min, max). Together with fr-units minmax(min, max) is a powerful combination to plan your escape from having to use media queries!
  3. Finally, we automatically re-scale the images and the middle column to the original full-width layout (using minmax or min-width and max-width on parent scaffold container) or (if you’re still stuck in the past…) by switching the property grid-template-columns back to 5fr 3fr 2fr 700px 2fr 3fr 5fr using media queries.

I can’t tell you whether to use minmax or min-width & max-width or media queries. That’s the choice I leave up to you. Personally, I started to develop the habit of using minmax in every single layout I create from now on, because it accepts complex values and shortens source code.

You might not fully get away from media queries anyway. Changing font size for mobile views, for example.

In Conclusion

Grid can get complicated. But by focusing on just a couple of properties, it allows you to develop a design technique you feel comfortable with.

Is it possible to create this same layout using only flex or other grid properties? Of course! This is by no means the standard or even the best way of creating blogging or article-like layouts.

But what’s important is that a firm choice was made. We may have limited ourselves to just a few CSS grid properties. The result? The code turned out to be clean and uncomplicated. It’s easy to read and maintain.

Get More Freemium via Social Networks

You can follow me on Twitter for weekend PDF giveaways.

Follow me on Instagram for a quick hit of JavaScript.

You can follow me on Facebook for free coding stuff.

Limited Time Offer

The diagrams in this tutorial were influenced directly by the manuscript!

CSS Visual Dictionary 28% OFF for Medium readers.

28% OFF

Medium Readers Only:

CSS Visual Dictionary

== grab a copy ==

Contains all CSS properties.

Issues. Every webdev has them. Published author of CSS Visual Dictionary https://amzn.to/2JMWQP3 few others…