Related article: to also get a good idea of how flex works try flex layout editor on this page.
This tutorial explains (almost) everything about CSS grid layouts. I am still working on minmax and auto flow, and will update this page soon as the content becomes available.
Technically, CSS box model is not part of WC3 specification.
But if there was one... It would probably look like this:
CSS Grid calls columns and rows tracks.
Notice negative coordinate system. You can specify grid lines using positive and negative values.
You can span content across multiple cells, much like an HTML table span.
But CSS grid is very different from HTML table.
In this tutorial we'll take a look at what CSS Grid brings to the table!
Book designers care about margins – essentially an invisible element of book design.
It may not seem like much but remove margins – the element that the reader is least aware of – and the whole reading experience turns awkward.
Readers notice lack of margins only when they are absent. Therefore – as a designer (of anything) it is imperative to pay equal attention to the invisible elements of design. We can always just plug in the content into the layout. Could it be then... that when we design with CSS grid, all we’re doing here to create beautiful layouts is working with an advanced version of book margins? Could be. That's just an opinion of one person.
CSS Grid goes beyond designing using margins in books, but the principle of invisible design remains the same. Things we cannot see are important. They are important to the visitors of your website, even if they don't even know it. In CSS grid this concept is thought of as gaps.
First... we will need a container and some items.
A CSS grid flow can go in either direction. But by default it’s set to row.
This means that if all other defaults are untouched your items will automatically form a single row where each item inherits its width from the grid’s container element:
To create a CSS grid from a blocking element simply set its display property to grid. Note that by default grid-auto-flow is set to row. This is why your items will “flow” over to the next row. However, if you need to change direction of the auto flow to columns you can do so by setting grid-auto-flow property to a value of column.
Your CSS grid container is a <div> element with: display: grid; and grid-template-columns and/or grid-template-rows properties that define... you guessed it... rows and columns.
Your CSS grid items are <div> elements inside your container. Each item behaves similar to a <td> tag in a <table> but with a lot more flexibility.
All that is just basic HTML.
When making CSS grid layouts we’re essentially defining a template. The grid will take up the empty space on the page, regardless of whether the number of items provided (3 divs in this case) fits into the template area in its entirety:
In this case CSS grid will assume that any new items added to the grid will fall into dashed squares unless other modifications are provided… at which we will look throughout this tutorial.
Let’s start with this really small template to demonstrate some core concepts.
Let’s dig down to the core of CSS grid by using minimum parameters:
To start getting to know CSS grid, let’s take a look at this first simple example. Here we have grid-template-columns and grid-template-rows CSS properties defining basic CSS grid layout.
These properties can take multiple values (which you should separate by space) that in turn become columns and rows. Here we used these properties to define a minimalist CSS grid composed of two columns (100px 160px) and one row (25px.)
In addition, the gaps on the outside border of the grid container do not add extra padding even when gap size is defined. Therefore they should be thought of as defined right on the edge. Gaps between columns and rows — on the other hand — are the only ones that are affected by gap size.
One thing you will notice about CSS grid right away is the definition of gaps. This is different from what we’ve seen in any other CSS property before. Gaps are defined numerically starting from the upper left corner of the element.
There are columns - 1 gaps between columns & rows - 1 gaps between rows. Watch out for the outer lines, they are not affected by gap size. They just form an outer border of your entire grid. However, gap count does includethose outer lines which are referred to as gap line 1 or column line 1 by default.
CSS grid does not have a default padding, border, or margin and all of its items are assumed to be content-box by default. Meaning, content is padded on the inside of the item, not outside like in all other common blocking elements.
That’s one of the best things about CSS grid in general. Finally we have a new layout tool that treats its box model as content-box by default.
Gap size is set individually per row or column by grid-row-gap and grid-column-gap properties or together by grid-gap for short.
CSS grid automatically adjusts position of each item on the grid depending on size and span of surrounding items. And sometimes it makes room for existing items even if column or row values are missing. It will make a best guess.
For example, if you specified only 2 columns with grid-template-columns set to 100px 160px and grid-template-rows set to 25px as shown in next example… but you actually have 4 items in the grid container CSS grid will then automatically decide how the new row should behave... even if it was not explicitly specified by you.
Here grid-template-columns was set to 100px and 160px. And grid-template-columns was set to 25px. However, because there are 4 items in the container, CSS grid made the decision to extend them into an implicitly created space. Notice that the columns in this new implicit row automatically inherited the row height from previously specified grid-template-rows property, even though it was not explicitly specified. From now on in this tutorial whenever you see blue grid items it means CSS grid arranged them automatically. Sometimes they are called implicitly specified items.
In this case we only have 3 items. There isn’t anything CSS grid can do about it so the item is left blank.
This phenomenon can be also observed when you make items span across multiple rows or columns (similar to rowspan and colspan in a <table>.)
Spanning multiple rows or columns with grid-column-start, grid-column-end, grid-row-start and grid-row-end will produce implicit alignment for any items that fall outside. More on this in just a moment.
An observation: All in all — with default gap values — CSS grid behaves a lot like some type of a <table> that supports implicit items for “leftover” cells:
Although the rules are strikingly similar let’s consider that only an observation… CSS grid is a lot more capable than mere mortal </table>.
Let’s take a look at the rest of CSS grid capabilities to find out the differences.
The grid-auto-rows property can be used to tell CSS grid to use a specific height for automatic (implicitly created) rows.
Instead of inheriting from grid-template-rows we can tell CSS grid to use a specific height for all implicit rows that fall outside of your definitions.
You can specify a different value for implicitly created columns or rows.
Bear in mind — of course — you can still set all of the values explicitly yourself:
Explicitly specifying dimensions of all rows and columns.
In a way CSS grid’s grid-auto-flow: column imitates Flex-like functionality:
You can make your CSS grid behave similar to Flex by overwriting its grid-auto-flow property’s default value of row to column. Note that here in this example we also used grid-auto-columns: 25px to determine the width of consecutive columns. This works in the same way as grid-auto-rows in one of the previous examples except this time the items are stretched horizontally.
CSS grid is excellent for creating traditional website layouts with two smaller columns on each side. There is an easy way to do this. Simply provide auto as a value to one of the widths in your grid-template-column property:
This is what happens with grid-template-columns: 100px auto 100px
Your grid will span across the entire width of the container or the browser.
As you can see already CSS grid offers a wide variety of properties to help you get creative with your website or application layout! I really like where this is going so far.
Okay... but what about the gaps... Dammit, those gaps again.
We already talked about the gaps. Mostly the fact that they cover the space between columns and rows. But we haven’t talked about actually setting them:
grid-column-gap is used to specify vertical gaps of equal size between all columns in your CSS grid.
I intentionally left the horizontal gaps clasped to their default value of 0.
That’s because I just wanted to provide a few visually descriptive diagrams that demonstrate some potential layouts.
I can already envision a Pinterest-like design with multiple columns using the setup above.
Likewise, using grid-row-gap property we can set horizontal gaps for the entire grid.
This is the same thing, except with horizontal gaps.
Using grid-gap property we can set gaps in both dimensions at the same time:
It is possible to set the gaps on entire CSS grid by using short-hand property grid-gap. But this means that gaps in both dimensions will be set to the same value. In this example it is 15px.
You can set gaps individually for each of the two dimensions.
The next 3 diagrams were created to demonstrate the different possibilities made possible by CSS grid that can be useful in various cases.
Simply use grid-column-gap: 42px and grid-row-gap: 15px
Here gaps are set individually per row and column which allows for varied column design.
In the example above wide column gaps are used. You can probably use this strategy for crafting image galleries for wide-screen layouts.
Here is the same thing as the previous example. Except we’re using wider CSS grid row gaps.
I really don’t see much use for the layout setup above. But it’s nice to know that it’s one of the possibilities here.
One thing I was disappointed about was the lack of support for the ability to create varied gap sizing within the same dimension. I think this is the most daunting limitation of CSS grid. And I hope in the future it gets fixed.
The following layout cannot be created using CSS grid:
Varied gap sizing is currently (April 14, 2018) not a possibility with CSS grid.
I’ve been suggested to use columns instead of gaps to achieve this function, every time I bring this up on my Twitter feed.
It might work but I don’t think that in 2018 we should have to descend to what essentially is a CSS hack in a situation for which there isn’t a good reason to exist in the first place.
One recent addition to CSS language is the fr unit.
The fr units can be used on things other than CSS grid. But in combination with one they are magical for creating layouts with unknown screen resolution... and still preserve proportion without thinking in percent.
The fr unit is similar to percentage values in CSS (25%, 50%, 100%, etc) except represented by a fractional value (0.25, 0.5, 1.0…)
But although it could be 1fr is not always 100%. The fr unit automatically dissects remaining space. The easiest way to demonstrate this is by following diagrams.
Here is a basic example of using fr units:
An example of using the fr CSS unit.
This is great news for intuitive designers.
1fr will be 10/1 of 10fr regardless of how much space 10fr takes up. It’s all relative.
Using 1fr to define 3 columns produces columns of equal width.
You can also use fractions.
Relative to 1fr 0.5fr is exactly half of 1fr.
These values are calculated relative to the parent container.
Can you mix percentage values with 1fr? Of course you can!
The example above demonstrates the differences between % (percent) units with fr. Guess what? There aren't any differences. The results are always intuitive and produce the effect you would expect. Fractional units are percentages too, just easier to use. They are more intuitive, because they take into account the remaining space available.
Fractional fr units are relative to themselves within some parent container.
Using fr units and increasing column gaps at the same time will produce the following result. I just wanted to include this here to demonstrate that fr units will be affected by gaps too:
5 different CSS grids used here to demonstrate how we should be mindful of the gaps when designing with fr units.
And just to be complete you can use fr units to create something like this:
A skewed chess board created using fr units to determine both row and column dimensions.
Although I don’t know where you would require such a dinosauric layout it clearly demonstrates how fr units can affect both rows and columns.
CSS grid allows the use of repeat property value.
The repeat property takes two values: times to repeat and what to repeat.
At its basic this is how it works:
Here we’re using grid-template-columns with repeat and without repeat to produce exactly the same effect.
Here grid-template-columns are provided two different sets of value to produce the same effect. Obviously repeat saves a lot of hassle here.
Final verdict: to save yourself from redundancy in cases where your grid must contain repetitive dimension values use repeat as a remedy.
The repeat property can be sandwiched between other values:
grid-template-columns: 50px repeat(3, 15px 30px) 50px;
In this example we repeat a section of two columns 15px 30px for 3 times in a row. I mean in a column. Ahh! You know what I mean.
Using CSS grid spans you allow your items to stretch across multiple rows or columns. This is a lot like rowspan and colspan in a <table>.
We will create a grid using repeat to avoid redundant values. But it could have been created without it — anyway, let’s make it our specimen for this section.
When we add grid-column: span 3 to item #4 a somewhat unexpected effect has occurred:
Using grid-column span 3 to take up 3 columns. However, CSS grid makes a decision to remove some of the items, because the “spanned” item cannot fit into suggested area.
In CSS grids spans can also be used to cover multiple rows. And if it so happened that the column is now greater in height than the height of the grid itself the CSS grid adapt itself to this:
CSS grid is adapting itself in several cases where items go beyond Grid’s parent container.
You can also span across multiple rows and columns at the same time. I created this other minimalistic example just to quickly demonstrate limitations, even though in most cases this will probably not happen:
CSS grid fills in the blanks.
Pay attention to how CSS grid adapts to the items around spans that cover multiple rows and columns. All of the items still remain in the grid but intuitively wrap around other spanned items.
When I tried to break the layout with a large span I ended up with the following case that demonstrates the key limitations of CSS grid:
CSS grid replaces potential item cells with empty space in two distinct situations.
But it’s still a lot like a <table>. See my other CSS grid vs table tutorial where I show you the frightening similarities.
However... there is a solution to this layout problem.
Start and End
So far we used CSS grid spans to create multi-column and multi-row items that occupy a ton of space. But... CSS grid has another much more elegant solution to solve the same problem.
The grid-row-start and grid-row-end properties can be used to define the starting and ending point of an item on the grid Likewise, their column equivalents are grid-column-start and grid-column-end. The are also two short-hand properties: grid-row: 1/2 and grid-column: 1/2.
These work an a slightly different way than spans.
With -start and -end properties, you can physically move your item to another location in the grid. Let’s take a look at this minimalist example:
Using CSS grid’s grid-row-start and grid-column-start on an item (first item in this example) you have the ability to physically move an item within your grid to another location!
Here we’ve taken item 8 and (redundantly) specified its location using grid-row-start and grid-column-start. Notice however, this alone has no effect on item 8, because item 8 is already positioned at that location on the grid anyway. However, by doing this you can achieve span-like functionality if you also specify an ending location using grid-column-end and grid-column-end.
Interestingly, designers of CSS grid have decided for the direction of the span vector to be insignificant. The span is still created within the specified area regardless of whether starting or ending points are provided in reverse order:
Specifying item span regardless of the direction of the start/end points produces the same results.
Let’s consider this 6 x 4 CSS grid. If you explicitly specify an items’s column end position that goes outside the number of specified columns (>=7) you will experience this wonky effect:
Making column width of an item greater than the original number of columns specified in the CSS grid.
In this case CSS grid will adapt the resulting layout of your grid to what you see in the example above. It’s usually a good idea to design your layouts by being mindful of grid’s boundaries to avoid these types of scenarios.
You can use the shorthand properties grid-row and grid-column to same effect as above using / to separate values. Except instead of providing an end value, it takes width or height of the span:
We can use / character for this short-hand syntax.
What if we need to reach the absolute maximum boundary of the grid?
Use -1 to extend a column (or row) all the way to the end of CSS grid’s size when number of columns or rows is unknown. But be mindful of any implicit items (16, 17) slipping away from the bottom of the grid:
Using negative -1 value to count from right-most gap to left.
Then I tried to do the same with rows, but the results were more chaotic, depending on which combinations of values I provided. I know there are other ways of using / but for the sake of clarity I want to keep things simple.
I only used 10 items in this example. CSS grid seems to gracefully resize itself.
When I was experimenting with rows to do the same thing, it seems like 4 in grid-column: 2/4 had to be changed to 2/6... but only if grid-row: 2/-1 was specified.
What I found out though is that juggling around values here produced results that cannot be easily documented using visual diagrams.
Well, at least we get the basic idea here. You can extend either column or row all the way to the maximum boundary using -1. How one affects the other takes a bit of practice to figure out in some specific cases.
We can expand on this a bit. CSS grid has a secondary coordinate system, so to speak. And because it doesn’t matter which direction you use to make cross-column and cross-row spans you can use negative values:
Using negative values to specify column and row’s start and end, we can create the same span from previous examples, since CSS grid is coordinate system agnostic. You can use both positive and negative numbers!
As you can see CSS grid coordinate system is pretty flexible.
Let’s say you’ve gone to the great lengths mastering CSS grid item spans. You crossed the seas of implicitly generated rows and columns. Now you’re curious to see what else is in store for you.
As a web designer, I’ve for a long time craved a 360-degree multi-directional float. Prior to the grid all we had was the float property for blocking elements. I wanted to be able to float in the middle and on any corner of the container. Luckily, CSS grid can now be used to this extent.
This functionality is only limited to CSS grids’ align-self property and justify-self property and does not appear to work on any other HTML element. If your entire site’s layout is built using a CSS grid then it solves a lot of issues associated with corner and center element placement.
An example of using align-self and justify-self properties. The difference between the 9 squares is the combination of start and end values provided to the said properties to produce any of the results depicted above. I won’t mention all of these combinations here, because it’s quite intuitive.
Horizontal Align: Use align-self: end to align the content to the bottom of the item. Likewise, align-self: start will make sure content sticks to the upper border.
Horizontal Align: Use justify-self: start (or end) to justify your content left or right. In combination with align-self you can achieve placement depicted on any of the above examples.
Just to finalize this discussion here is how align-self affects a slightly more complex situation — one we’ve taken a look at before in this tutorial:
The align-self property makes it possible to align the item’s content vertically. You can do this by providing values: start, center and end.
You can use values start, center and end.
Note, however there aren’t top and bottom values for align-self.
Another property that does the same thing but horizontally is justify-self:
CSS grid item property justify-self in action using unset, start, center and end values.
You can use start|left or end|right values interchangeably here.
Template areas provide a way to refer to an isolated part of your grid by a predefined name. This name cannot include spaces. Use - instead.
Each set of row names is enclocss-grid-justify-self-horizontal-align.pngsed in double quotes. You can further separate these sets of row names either by a line break or by space to create columns as shown in the example below.
Although only 5 items are present template are names can logistically occupy places not yet filled with items:
Example of specifying template areas with grid-template-areas property.
Similar principle to specifying row and column size is followed here to name all of the areas in the grid. Just separate them by space or tab.
This syntax simply allows us to intuitively name our template areas.
But things get a lot more convenient when you start combining areas with the same name across multiple containers. Here I named 3 items in the left column Left and 3 items in the right column Right. CSS grid template areas automatically combined them to occupy the same space by name.
Spanning template areas across multiple grid “cells.” Simply name your columns and rows, and adjacent blocks will “merge” into larger areas. Just make sure to keep them rectangular!
It’s important to make sure that areas consist of items aligned into larger rectangle areas. Doing Tetris blocks here will not work. Straying from the rule of always keeping your areas rectangular is likely to break the CSS grid and/or produce unpredictable outcome.
Working with numbers (and negative numbers) can become redundant over time especially when dealing with complex grids. You can name grid lines with whatever you want using [name] brackets right before size value.
To name the first grid line you can: grid-template-column: [left] 100px.
Likewise, for rows it is: grid-template-row: [top] 100px
You can name multiple grid lines. The  brackets are inserted at an intuitive place in the set. Exactly where the grid line (a.k.a. gap) would appear:
grid-template-columns: [left] 5px 5px [middle] 5px 5px [right]
Now you can use the names left, middle and right to refer to your grid lines when creating columns and rows that need to reach that area:
CSS grid lets you name and refer to named lines - instead of a cell index number - as values. You can assign them via properties grid-template-columns and grid-template-rows. Each span in the diagram above refers to named lines and not the gap numbers. You can use any name you want, but you cannot use space character in the name.
If you use a space character between the brackets, as in [center middle] you will create two multiple names for that gap. You can now use either name to refer to that gap.
Naming gap lines creates a more meaningful experience designing your grid layouts. It’s a lot more intuitive to think of the middle line as center (or middle) instead of 4.
Well, this CSS grid tutorial covered almost everything there is to know about CSS grid using visual diagrams. I hope you enjoyed them and learned something new.
We now understand how to block out rectangular areas. Let's take a look at a potentially real-world scenario. Here I'll demonstrate a very basic layout.
I blocked a very simple website layout with two sidebars, a header and footer areas. The main area is in the center occupying 3 x 2 cell space:
Using grid-template-columnsgrid-template-areas property to create a simple website layout.We only need 5 items here. Add any more and they would be pushed outside of the main grid area into implicit cells.
Just make sure to always keep your areas square or rectangular.
The music is not in the notes, but in the silence between — Wolfgang Amadeus Mozart
This seems to be true of CSS grid also. And so many other things!
Stay up to date with Freemium CSS Tutorials.
When I release something, I make sure it's worth taking a look at — at least once.