Positioning elements on a web page properly has already caused a lot of headaches for web developers. I am no exception either. It has not happened once that I fiddled around with floating of block elements, positioning with inline-block and using the n-th clear statement to bring everything back to the normal HTML layout flow.
Although I have already heard of something like a grid layout in CSS, I never really looked into it or used it in practice until two weeks ago. Like nearly always there were many more important things to care about and anyway I was happy that I finally got my head around the flexbox layout some time ago. However, my last feature at work required me to craft a new web page from scratch and the proposed layout convinced me to give the CSS grid a try. To solidify my knowledge about it, I want to share the basics and most essential things I have learned so far with you by showing some examples.
How to define a grid
The starting point for my examples will be the following minimalistic HTML file which defines our grid.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS Grid</title>
<style>
.grid-container > div {
background: red;
border: 1px solid black;
}
</style>
</head>
<body>
<div class="grid-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
</div>
</body>
</html>
The result looks like in the figure below.
Regarding the HTML elements a simple grid always contains a container with element inside it. Let’s turn this container in an actual grid container with grid items. It’s as simple as adding the following styles.
.grid-container {
display: grid;
grid-template-columns: repeat(3, auto);
grid-template-rows: repeat(2, auto);
}
We basically say that the div with this class should be displayed as grid instead of block and it should have three columns and two rows (these are called grid items). The auto attribute tells the container that the space should be distributed fair among the items. They will have the same width each.
If you want to have some space between the grid items, add something like grid-gap: 10px
to the container and it will look like following.
If you only want to to make a space between the grid rows or columns use the specific grid-column-gap
and grid-row-gap
properties. By the way, the column and row specific properties exist for many properties but often it is easier to use the shorthand syntax if you wanto to apply the style to both rows and columns.
Positioning of grid items
Now, let’s turn from the container to the individual grid items. Sometimes not all your grid items should have the same width or height. With CSS grid you can easily expand and collapse grid items however you want. Let’s assume we want to make the first item bigger as it should be more prominent on our page, let’s say it should span the first two columns and two rows.
.item1 {
grid-column: 1 / 3;
grid-row: 1 / 3;
}
Defining this style and adding item1 to the first div within the grid container does the trick. Pay attention that the numbering always starts at the first grid line and it is one-index based.
Provide names for your grid
Withgrid-template-areas
you can provide names for your grid items and access them by their names in CSS. Imagine a typical web page layout with a header, a nav, an aside, some content and a footer. Let’s modify our example a bit to make clear how this works.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CSS Grid</title>
<style>
.grid-container {
display: grid;
grid-template-columns: 100px auto;
grid-template-areas:
"header header"
"nav nav"
"aside main"
"footer footer";
grid-gap: 10px;
}
.grid-container > * {
border: 1px solid black;
}
header {
grid-area: header;
background: red;
}
nav {
grid-area: nav;
background: blue;
}
aside {
grid-area: aside;
background: green;
}
main {
grid-area: main;
background: yellow;
}
footer {
grid-area: footer;
background: aqua;
}
</style>
</head>
<body>
<div class="grid-container">
<header>1</header>
<nav>2</nav>
<aside>3</aside>
<main>4</main>
<footer>5</footer>
</div>
</body>
</html>
As you can see we define template areas within our grid container which we match for every grid item. We have defined two columns and four rows whereby the first column is only 100px wide because we do not need more for the aside in this case. The rest will be filled up with auto.
Auto-fill and auto-fit
There are two more interesting properties I would like to mention in this post, namely auto-fill and auto-fit. However, they are a bit more tricky to understand in my opinion. So, give me a try to explain them in simple terms. Let’s assume we have a simple grid with a container and six gid items where the CSS looks like the following.
.grid-container {
display: grid;
grid-template-columns: repeat(6, 200px);
grid-gap: 10px;
background: aqua;
}
.grid-container > div {
background: red;
border: 1px solid black;
}}
This grid basically has just one row with six columns. So not a very fancy grid but just good enough for this purpose. All grid items will have a length of exactly 200px. In a full width browser window on a desktop computer all items will be on one line and visible.
You will realize as soon as you minimize the width of the browser window that the items will not scale its width down.
This is clear since we hardcoded the width as 200px. Probably not the optimal behavior we desired to have. It would be nicer if the items wrap in case they do not fit anymore on one line. grid-template-columns: repeat(auto-fill, 200px);
does exactly what we want. It creates as many grid items on the line with a width of 200px as it can fit. However the ones we do not use are invisible ones and you will only see them in your developer tools of your browser. If the browser is at full width and all used items fit on the line there is no difference, but as soon as you start to make the window smaller and items do not fit anymore they will be wrapped onto the next row.
A very handy extension is using the minmax()
attribute here. This way we can specify a minimum width criteria for the grid items as well as a maximum one. Take a look at the example.
grid-template-columns: repeat(auto-fill, minmax(100px, auto));
This tells the grid items that they can grow as long as no additional item finds a place on the same line and shrink until a minimum of 100px before wrapping onto to the next line.
In combination with minmax()
there is another attribute, namely auto-fit
which can make sense in certain situations. Similar to auto-fill
it also introduces as many elements as it can fit but the difference is that the ones we do not use explicitly wil be resized to a width of zero. The remaining space will be distributed among the used ones instead. You will see this effect immediately if you have the browser window maximized as the grid items use up all the width of the window. This is also shown in the figure below.
Conclusion
I hope I could summarize my learnings regarding CSS grid expressive enough with my provided examples and explanations. It’s actually not that hard to understand the basic layouting techniques and philosophy of CSS grid. I did not dive into any little detail about it in this blog post as I am also not yet a CSS grid expert, but the ones I illustrated get you very far as I have seen in my practical work so far. If you want to learn about how to align grid items which do not use the full dimensions of a container horizontally and vertically and are curious about a few more things I have not talked about in this post, I highly recommend the article from css-tricks. If you know the awesome guide to flexbox article, this one will be very familiar to you. Another great resource is the laracast series about CSS grids. All of the information in my blog post is actually based on these two great resources. As a final sentence I want to say that CSS grids to me are awesome for a lot of different layouts and make certain positioning tasks easier, cleaner and without the messy hacks you had to do before.