Barbarian Meets Coding
barbarianmeetscoding

WebDev, UX & a Pinch of Fantasy

10 minutes readcss-griddraft

CSS Grid

What is CSS Grid?

For years web developers have been creating grid-like layouts for the web using different techniques which were never meant to solve this use-case like tables, inline-blocks and floats of relative sizes, flexbox, etc. The CSS Grid Layout is a native way to create grid-like layouts for the web in CSS.

Using CSS grid you can completely separate the semantics of your document from its visual representation (no more need for loads of wrapper elements to describe rows, columns, etc) and since it is fully defined in CSS it works great with media queries for responsive layouts.

CSS Grid Conceptually

At its core, a CSS grid is composed of a container, which is divided in tracks (rows and columns), which are collections of cells delimited by lines and which can be grouped in areas.

  • A grid container is the element that represents the grid itself and contains all the grid items as direct children.
  • The grid lines are the lines that delimit each column and row within the grid.
  • The grid tracks are the spaces between two grid lines vertically or horizontally. This is what we commonly refer as columns and rows. You can use the term grid track as a generic way to refer to either columns and rows.
  • A grid item or grid cell is the intersection between a column and a row, or, the space delimited by 4 grid lines.
  • A grid area is an arbitrary grouping of adjacent cells delimited by four grid lines. A grid area can consist on one or more adjacent cells, and will have a rectangular shape.

Why should you care about all this terminology? Well, when learning and using something it is useful to have a mental model that you can use to reason about a CSS grid and so that you can communicate with others clearly. But, more importantly, the CSS grid API takes advantage of all these items to help you define your grids.

CSS Grid Basics

Let’s say that we have have a spell book composed of different spells:

<div class="spellbook">
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
  <div class="spell"></div>
</div>

By default, using vanilla CSS layout rules each of these items is going to be laid out as a block (taking the full width of its parent container) one after the other:

CSS Grid comes with a new set of CSS properties for transforming layouts into grid layouts. It all starts with the display: grid property (very reminiscent of flexbox):

.spellbook {
  display: grid;
}

/* These are all display modes available for grid containers */
.grid-container {
  display: grid;        /* grid as block element */
  display: inline-grid; /* grid as inline element */
  display: subgrid;     /* for grid cells which in turn are grid containers */
}

When you use display: grid all the direct children of the grid element will be treated as grid items. At this point, you won’t see any changes in your layout because by default a grid has a single column of items.

We can further describe the layout of the grid by specifying how the tracks (columns and rows), and the spacing should look:

.spellbook {
  display: grid;

  /* 
  The sizes don't need to be in pixels. 
  We'll later see that there's lots of units 
  and functions that you can use to determine 
  how the tracks will look like.
  */
  grid-template-rows: 20px 50px 100px;
  /* 
  auto means that the column will take all 
  the remaining space available.
  */
  grid-template-columns: 20px 25px auto 10px;
  grid-gap: 25px;
}

Grid Tracks

So tracks can be defined using two properties:

  • grid-template-columns to define the column tracks
  • grid-template-rows to define the row tracks

These properties which might look simple at a glance are really powerful as you’ll see in a bit. In their most basic form, they let you define how many rows and columns a grid has in addition to their sizes:

.spellbook {
  display: grid;
  /* Three rows of 20px, 50px and 10px height respectively. */
  grid-template-rows: 20px 50px 10px;
  /* Three columns of 20px, 25px and 10px width respectively. */
  grid-template-columns: 20px 25px 10px;
  /* Gap between cells is 25px. */
  grid-gap: 25px;
}

But you’re not limited to using pixels, you can use any sizing unit that you’re familiar with. Even better, CSS grid comes with a new unit called fr (fraction unit 1).

The Fr Unit

The fraction unit fr represents a fraction of the available space in the grid container and it allows you to size tracks in relation to each other (in a similar way to flex). For instance:

.spellbook {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

means that we want a grid with two columns of equal width which grow and shrink to fill the available space:

Whereas this other example:

.spellbook {
  display: grid;
  grid-template-columns: 1fr 2fr 3fr;
}

means that we want a grid with three columns where the third column is three times as big as the first one, and the second column is twice as big as the first one.

Helper Functions

CSS Grid has a couple of very useful helper functions that you can use when defining your tracks:

  • repeat lets you quickly repeat track size definitions, that is, it allows you to specify a number of tracks with a given length inside either grid-template-columns or grid-template-rows
  • minmax lets you define minimum and maximum sizes for a given column or row

This snippet below:

.spellbook {
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr);
}

defines a grid with 5 columns where the first one is twice the width of each one of the remaining 4 columns.

This is equivalent to the snippet below but with less code:

.spellbook {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr 1fr;
}

And you’re not limited to repeating only a column, you can use repeating patterns as well:

.spellbook {
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr 2fr);
}

which alternates columns of 1fr and 2fr four times.

The minmax function allows you to specify mininum and maximum sizes for a given row or column.

For instance, let’s say that you want to specify that a row will be at least 200px high and grow to be at most half the size of the other row:

.spellbook {
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr);
  grid-template-row: minmax(200px, 1fr) 2fr;
}

Or grow to take as much height as it needs to represent its content:

.spellbook {
  display: grid;
  grid-template-columns: 2fr repeat(4, 1fr);
  grid-template-row: minmax(200px, auto) 2fr;
}

Why are there rows if I didn’t defined any?

In somes cases some grid items will fall out of whatever you’ve specified in your grid styles. For instance, this can happen if you only define the column track, or if there are so many grid items that can be fitted in the grid tracks you have defined.

What happens to these grid items?

CSS grid has the concept of an explicit and an implicit grids. The explicit grid is that which you define in your CSS rules whereas the implicit grid is that which applies to whichever grid track or item that falls out of these rules.

The default behavior for the implicit grid is to automatically resize based on their content. If you want to change this default behavior you can use the grid-auto-rows and grid-auto-columns property which will apply to the tracks in the implicit grid.

For instance, this grid:

.spellbook {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

will have all rows take as much as it’s required by each rows’ content whereas this other grid:

.spellbook {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 10px;
}

will have all rows take 10px.

Finally, this grid:

.spellbook {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 10px 50px;
}

alternates row between 10px and 50px. For more information on the type of values you can use for grid-auto-rows and grid-auto-columns check MDN.

Gutters

CSS Grid comes with some properties you can use to define the gutters (the space) between grid cells:

  • Use row-gap to define the space between rows
  • Use column-gap to define the space between columns
  • gap is a shorthand for the rules above and lets you define the space between rows and columns at once
.spellbook {
  display: grid;
  grid-template-columns: 1fr 1fr;

  row-gap: 25px;
  column-gap: 1rem;
  gap: 25px 1rem;
}

More Advanced CSS Grid Use Cases

Auto-fit and Auto-fill

Positioning Items Using Grid Lines

Nesting Grids

Layering Grid Items

Tooling for Working With CSS Grid

Chrome Dev Tools

Firefox Dev Tools

Patterns

CSS Grid vs Flexbox?

Flexbox is for one-dimensional layouts - anything that needs to be laid out in a straight line (or in a broken line, which would be a single straight line if they were joined back together). Grid is for two-dimensional layouts. It can be used as a low-powered flexbox substitute (we’re trying to make sure that a single-column/row grid acts very similar to a flexbox), but that’s not using its full power. Rachel Andrew citing Tab Atkings

Resources

So the spec doesn’t specify what fr are called exactly but since they represent a fraction of leftover space in the grid container let’s say they are fraction units.



Jaime González García

Written by Jaime González García , dad, husband, software engineer, ux designer, amateur pixel artist, tinkerer and master of the arcane arts. You can also find him on Twitter jabbering about random stuff.Jaime González García