Blog

Learning CSS Grid

Edit this Post Opens in new tab

CSS Grid Course Website by Wes Bos Opens in new tab

a screenshot of the css grid course website by wes bos

I really liked the JavaScript30 Opens in new tab course by Wes Bos Opens in new tab, where you get to code 30 different projects with plain JavaScript. Now he published another course which is also available for free. This time it's all about learning CSS Grid Opens in new tab. In this blog post, I will document everything I learned about CSS Grid in the course.


What you can learn from this blog post:


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 Opens in new tab 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-rows and grid-auto-columns, you can style any implicitely created row or column.

CodePen - CSS Grid - Implicit vs. Explicit Tracks Opens in new tab

Grid-auto-flow

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 implicit tracks.

This means grid-auto-flow is set to row by default. If you set grid-auto-row to column, the third item will be automatically put into a new column next to the other items.

CodePen - CSS Grid - grid-auto-flow Opens in new tab

Sizing tracks

The fr unit represents the amount of space left after all elements are laid out.

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.

CodePen - CSS Grid - sizing tracks Opens in new tab

Repeat function

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);
CodePen - CSS Grid - repeat function Opens in new tab

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 for grid-row: span 2.

CodePen - CSS Grid - sizing grid items Opens in new tab

Placing Grid Items

There are also better ways to position grid items than just sizing them. With grid-column-start and 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 so with 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.

CodePen - CSS Grid - Placing Grid Items Opens in new tab

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.

CodePen - CSS Grid - Spanning and Placing Cardio Opens in new tab

auto-fit and auto-fill

With the auto-fill expression inside the grid-template-columns declaration 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".

So grid-template-columns: repeat(auto-fill, 150px); does that.

The difference between auto-fill and auto-fit is visible when you have not enough items to fill the grid.

With 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, auto-fit ends 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 auto-fit and auto-fill.

CodePen - CSS Grid - auto-fill & auto-fit Opens in new tab

Using minmax for responsive grids

With 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 minmax() and the browser window gets smaller; they will automatically jump into the next row.

The CodePen example below also shows the difference between auto-fit and auto-fill in combination with minmax().

CodePen - CSS Grid - Using minmax() for Responsive Layouts Opens in new tab

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 item with 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.

CodePen - CSS Grid - Grid Template Areas Opens in new tab

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 grid-template-columns and grid-template-rows 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];
CodePen - CSS Grid - Naming Lines in CSS Grid Opens in new tab

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 Opens in new tab 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.

CodePen - CSS Grid - grid-auto-flow block formatting Opens in new tab

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. justify-_ defines everything on the row axis, and align-_ defines everything on the column axis.

With justify-items and align-items, you can define the alignment for your grid items on the grid container. There is also a shorthand called place-items 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 justify-content and align-content to align them as one inside your grid container.

Finally, with justify-self and align-self, you can overwrite the alignment settings on the container and specify them on a single grid item.

CodePen - CSS Grid - Alignment and Centering Opens in new tab

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 re-ordering.

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.

CodePen - CSS Grid - Re-ordering Grid items Opens in new tab

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 1fr.

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 width of 150px and the text takes all the remaining space. Vertical alignment is also possible.

display: grid;
align-items: center;
grid-template-columns: 150px 1fr;
CodePen - CSS Grid - Nesting grid with album layouts Opens in new tab

CSS Grid image gallery

The next example is about building an image gallery with CSS Grid. The basic grid for this consists of repeating columns and rows that are 100px wide and high. This example is extended with a little bit of JavaScript to give each image a different width and height.

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 grid-auto-flow 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.

CodePen - CSS Grid - Flexbox vs. CSS Grid Opens in new tab

Recreating CodePen

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.

CodePen - CSS Grid - Recreating CodePen Opens in new tab

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.

CodePen - CSS Grid - Bootstrappy Grid with CSS Variables Opens in new tab

Responsive Website

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 expanded.

Additionally, it has the aria attribute aria-controls="menu-list" which indicates that the button controls the element with the class of menu-list which is, in this case, the navigation.

By changing the values of these attributes with JavaScript, you can toggle the menu easily.

CodePen - CSS Grid - Responsive Website Opens in new tab

Full bleed blog layout

The last example is about building a blog layout with sections of different width and elements.

CodePen - CSS Grid - Full bleed blog layout Opens in new tab

Sources & further reading


I hope you enjoyed this post and learned something new. If you have any questions, feel free to reach out to me via Email Opens in new tab.

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