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 tracksgrid-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 eithergrid-template-columns
orgrid-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
- CSS Grid - Table Layout is Back. Be There And Be Square
- Grid by Example has everything on CSS Grid Layout by Rachel Andrew. Start with Get Started with Grid Layout
- A Complete Guide to Grid.
- Basic Concepts of the CSS Grid Layout and the complete CSS Grid Layout docs on MDN.
- CSS Grid course by Wesbos
- CSS Grid cheatsheet. Thanks to @sulco for sharing this
- Flexbox cheatsheet. Thanks to @sulco for sharing this
- CSS grid specification
- Can I use CSS Grid?
- CSS Grid Concepts Explained
- Using CSS Grid: Supporting Browsers Without Grid
- Books
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.
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.