Barbarian Meets Coding Titlebarbarianmeetscoding

WebDev, UX & a Pinch of Fantasy

css-grid

Wiki: CSS Grid - Finally

What is CSS Grid?

For years web developers have been creating grid-like layouts for the web using different techniques which were never mean 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.

// Drawing

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, moreover, the CSS grid API is going to take advantage of all these items to let 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 this 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 */
}

Once this property is setup, 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 since by default a grid has a single column of items. We can further detail the layout of the grid by defining 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 although simple at a glance are really powerful as you’ll see in a bit. In their most basic form they allow you to define how many rows and columns a grid has in addition to their sizes as you saw above:

.spellbook {
  display: grid;
  grid-template-rows: 20px 50px 10px;
  grid-template-columns: 20px 25px 10px;
  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

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 1f;
}

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 2f 3f;
}

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 comes with a couple of very helpful 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 on the other hand 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 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, 1fr) 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 (space) between grid cells:

  • row-gap lets you define the space between rows
  • column-gap lets you define the space between columns
  • gap is a shorthand for the 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

Positioning Items Using Grid Lines

Nesting Grids

Layering Grid Items

Tooling for Working With CSS Grid

Chrome Dev Tools

Firefox Dev Tools

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


  1. 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, Front-end software engineer, UX designer, amateur pixel artist, tinkerer and master of the arcane arts. You should follow him on Twitter where he shares useful stuff! (and is funny too).Jaime González García