Learning CSS Grid
CSS Grid Course Website by Wes Bos ↗
What you can learn from this blog post:
- General setup and basics of CSS Grid Development
- Implicit vs. explicit Grid
- Sizing tracks
- Repeat function
- Sizing Grid items
- Placing Grid items
- auto-fit and auto-fill
- Using minmax() for responsive grids
- Grid template areas
- Naming lines in CSS Grid
- Grid-auto-flow dense block fitting
- CSS Grid alignment + centering
- Re-ordering Grid items
- Real-world examples
General setup and basics of CSS Grid development
In the first few videos, Wes talks about the tooling setup for the course. He uses browsersync ↗ for the local development which is an npm package that automatically updates your browsers once you change the HTML, CSS, images, or other project files.
It is such a great tool I couldn't work without, and that is why browsersync has had its safe spot in my build tool setup with gulp for a long time.
Wes also talks about the basics of CSS Grid development with the firefox
developer tools. The basic principle reminds me of flexbox. You always have a
parent where you set
display: grid and define the settings for columns, rows,
and the gap between them.
Child elements inside this parent can be positioned separately. The firefox dev tools have a special layout window included where you can highlight the grid View and also show the numbers of the grid cells, which is extremely helpful when developing CSS Grid.
Implicit vs. explicit Grid
The difference between explicit and implicit grid tracks is simple. When you
explicitly define grid columns with
grid-template-columns: 100px 100px you get
explicit grid tracks.
If the browser notices that there is not enough space for all your items he automatically creates a second row.
So these tracks are called implicit because the browser creates them and not explicitly you.
The same applies if you have four items and define two rows. If you now add two
more items, the browser implicitly creates a new row. With
grid-auto-columns, you can style any implicitely created row or column.
If you have two items, define two columns using
grid-template-columns: 200px 400px and then add a third item, the browser will
put this item automatically in a new row below like, described before, with
grid-auto-flow is set to row by default. If you set
column, the third item will be automatically put into a new column next to
the other items.
fr unit represents the amount of space left after all elements are laid
If you define three columns with
grid-template-columns: 200px 200px 1fr, the
first two columns will be 200px wide, and the last one will take up all the
space that is left.
fr stands for fractional unit, but Wes likes to call it free space which
helps with remembering the idea of the fr unit.
It is also possible to use the auto keyword. Then an item will be sized according to the content it contains.
Instead of writing:
grid-template-columns: 1fr 1fr 1fr 1fr;
you can simply use the CSS Grid repeat function and write:
grid-template-columns: repeat(4, 1fr);
Sizing Grid Items
By default, grid items just flow one after another, and as there is space for each one, they will fit themselves into the grid as they can.
There is also a way to more precisely size grid items inside a parent grid
container. The instruction
grid-column: span 2 tells the browser to size the
specific child element with the space and width of two columns. The same goes
grid-row: span 2.
Placing Grid Items
There are also better ways to position grid items than just sizing them. With
grid-column-end you can define where a grid item
should start and where it should end. There is also a shortcut property for this
grid-column: 2 / 5, the grid item starts with the second column and
ends before the fifth.
You can also define that the grid item should start at the first column and span
over two columns with
grid-column: 1 / span 2.
If you want your grid item to start at the first column and span over the last,
but you don't know how many columns you have, just use
grid-column: 1 / -1.
The second CodePen example below shows all the different ways to place grid items inside a grid container. Have a look into the CSS to check how it is done.
auto-fit and auto-fill
auto-fill expression inside the
you can tell the browser, "hmm, I'm not sure how many columns I want, make each
150px wide, for example, and then fill it with as many columns as possible".
grid-template-columns: repeat(auto-fill, 150px); does that.
The difference between
auto-fit is visible when you have not
enough items to fill the grid.
auto-fill the grid will create as many columns as possible, although you
don't have enough items. So if you have four items and there is space for six,
the explicit grid ends after six items. In comparison to that,
the grid when all available items are placed inside your grid.
In the CodePen example below, open the firefox dev tools, enable the grid view
in the layout window, and you will see the difference between
Using minmax for responsive grids
minmax(), you can tell the browser to make the items in a column a
minimum width of
150px and a maximum width of
1fr, for example. So the items
will automatically adapt to the available space.
This is also a great way to create a responsive grid without media queries.
When the grid items already have the minimum width declared with
the browser window gets smaller; they will automatically jump into the next row.
The CodePen example below also shows the difference between
auto-fill in combination with
Grid template areas
Grid Template areas come in handy for building a whole layout of a page. Say you want to have two sidebars left and right and a content place between them. Below you want to have the footer spanning over the whole row.
With grid template areas, you can type your grid parent into the
grid-template-areas instruction exactly how you want the layout to look.
On the grid items, meaning the child items of the parent, you then tell each
grid-area which part of the layout it should be. That's it! Simple
and easy full-page layout.
The firefox dev tools also offer the possibility to display your grid area names so you can quickly check if your layout is displayed as you wish it to be.
Naming lines in CSS Grid
By default, you declare to span your grid items over the columns and rows by
using the line names 1,2,3, and so on. CSS Grid also offers the possibility to
rename your line names on the
declaration on the parent.
So if your initial declaration for the columns and the rows on the grid container is like this:
grid-template-columns: 1fr 500px 1fr; grid-template-rows: repeat(10, auto);
and you want to span an item inside the middle column from the top to the tenth line you would say:
grid-column: 2; grid-row: 2/10;
By renaming your columns and rows, you can now position your item inside this grid using the new line names.
grid-template-columns: [site-left] 1fr [content-start] 500px [content-end] 1fr [site-right]; grid-template-rows: [content-top] repeat(10, auto) [content-bottom];
Grid-auto-flow dense block fitting
Grid-auto-flow is, by default, set to row, so every item that does not fit in the same row will automatically be put into a new row below. This can be helpful but also not really useful in a lot of cases.
If you have a grid with ten columns and you want every sixth item to span over
six columns, there will be a lot of empty space because the six-column-long item
often can't fit in the same row and is put into the next row via
grid-auto-flow: row and the space left over is not filled with other items.
In this case, the dense value comes to help. MDN ↗ describes this value as follows:
"Dense is a keyword specifying that the auto-placement algorithm uses a 'dense' packing algorithm, which attempts to fill in holes earlier in the grid, if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items".
Go ahead and turn the
grid-auto-flow: dense instruction on and off in the
CodePen example below to see the difference.
CSS Grid alignment + centering
Flexbox made centering items on a page really easy. CSS Grid also has its ways to center items without problems.
There are two main properties that can be used for that.
everything on the row axis, and
align-_ defines everything on the column axis.
align-items, you can define the alignment for your
grid items on the grid container. There is also a shorthand called
which you can give two values, the first for the justify-_ property and the
second for the align-_ property.
If your grid items don't fill up your whole grid, you can use
align-content to align them as one inside your grid container.
align-self, you can overwrite the alignment
settings on the container and specify them on a single grid item.
Re-ordering Grid items
Imagine having a ten-column wide grid with a logo on the left that spans over two columns, a nav on the right that spans over eight columns, and a full-width content below.
It is possible to change the order of the logo and the nav easily so that the logo will be on the right and the nav on the left.
By default, every item has a value of 0 on the order property. So giving the nav
order: 0, the logo
order: 1, and the content
order: 3 will achieve the
It is important to mention that this technique will goof up the order a screen reader will read it, so it is kind of bad practice concerning accessibility if you use this on a bunch of paragraphs, for example. But for a nav and a logo, it does not matter that much.
Real World Examples
Nesting Grid with album layouts
In this example, you can see several album info boxes consisting of an image and a few details about the album. To achieve this layout, you have to define the columns on the main grid first, which contains every album info box.
With the following expression, you can define a grid that has columns with a
minimum width of
400px and a maximum width of
grid-template-columns: repeat(minmax(400px, 1fr));
So depending on the available space, the Grid will add columns or remove columns and shrink or expand them accordingly, which creates a fully flexible and responsive layout without media queries.
To achieve the layout inside the album info boxes, it is important to know that grid items can also be grid containers, as we know from flexbox already.
So you can add two columns into every album info box so the album image has a
150px and the text takes all the remaining space. Vertical alignment
is also possible.
display: grid; align-items: center; grid-template-columns: 150px 1fr;
CSS Grid image gallery
Therefore you have to make an array with a length of 50.
Array.from is pretty
useful in this case. Every Item of this array is an array itself consisting of
two random numbers between 1 and 4. These two values will describe the
horizontal and vertical length of the image.
For every item of the digits array, you then have to build the HTML, which consists of the image, an overlay, and a close button. By using ES6 destructuring, you can insert the randomly generated numbers for the horizontal and vertical values and use them as CSS class names.
By doing that, you will get 50 different images in the grid with a random row
and column-span between 1 and 4. Using the dense value on the
property, you can avoid having too many empty spots in between.
Another useful thing I learned here is that by setting two grid items in the same row and column, they will overlap. Very practical for adding overlay elements.
Flexbox vs. CSS Grid
In general, CSS Grid can do everything Flexbox can do. Some people say that Flexbox is for laying out elements in one dimension, and CSS Grid is for laying out elements in two dimensions.
In this example, Wes shows how things solved previously with flexbox can be done with CSS Grid and in what scenarios Flexbox is still the winner. You can find all the examples in the CodePen below.
In this example, you are recreating CodePen, the tool I have used to display all the examples before. CodePen is a development environment that allows you to write code in the browser and see the results immediately.
This example is good practice for learning to layout different sections of a page with CSS Grid. Basically, it is all about grids inside other grids.
Bootstrappy Grid with CSS variables
Bootstrap became very popular for implementing an easy way to use a responsive grid on a website. It implemented CSS classes for the orientation of your elements, how they should behave on different viewports, and how far they would span in your grid.
So a div with the class of
col-sm-4 would span over four columns on a viewport
equal to or greater than 768px wide.
In this example Wes shows how to achieve the Bootstrap principle with CSS Grid.
In this example, Wes shows how to build a whole responsive website with CSS Grid. He divides the page into several sections and then uses almost every technique of CSS Grid learned in the course to lay out the page.
Another thing Wes teaches here, and I liked, is the usage of aria attributes on buttons. So Instead of adding and removing a CSS class on the button, you can simply check the aria attributes value of the button and also use the aria attributes value for styling.
In this example, the button to open the navigation menu has the aria attribute
aria-expanded="false" which indicates by default that the menu is not
Additionally, it has the aria attribute
indicates that the button controls the element with the class of menu-list which
is, in this case, the navigation.
Full bleed blog layout
The last example is about building a blog layout with sections of different width and elements.
Sources & further reading
- The CSS Grid course by Wes Bos ↗
- A complete guide for CSS Grid by Chris Coyier ↗
- CSS Grid Layout by the Mozilla Developer Network ↗
- A collection of examples, videos, and other information to learn CSS Grid by Rachel Andrew ↗
- Auto-Sizing Columns in CSS Grid: 'auto-fill' vs. 'auto-fit' by Sara Soueidan ↗
- Layout Land, a YouTube Channel by Jen Simmons all about CSS Grid ↗
I hope you enjoyed this post and learned something new. If you have any questions, feel free to reach out to me on Twitter ↗ or via Email ↗.
If you want to support me, you can buy me a coffee. I would be very happy about it!☕️ Buy me a coffee ☕️
I wish you a wonderful day! Marco