How to Efficiently Master the CSS Grid — in a Jiffy
Learn the 20% you need for 80% efficiency with CSS Grid.
Introduction
This is NOT the article to learn “everything” about the css grid.
On the contrary, the target audience is people who want results quickly, and be productive while at it.
In the four parts of this article, I will show you the 20% you need for 80% efficiency with the CSS Grid layout.
Let’s dig in!
Why just 20%?
Where possible, a programmer seeks efficiency — the supposed lazy way out.
The CSS Grid layout is complex. In my opinion, more complex than Flexbox. (mehn, it took me weeks to figure out flexbox)
Not so because it is “difficult” but the CSS Grid has 18 new properties plus other concepts you’ve never heard of anywhere else in CSS.
So, do you need all of these new properties now? Right now?
No, you don’t!
Just learn the bit to get you results now. You can go ahead to learn the other properties later. This is my definition of “efficiency with the CSS Grid layout”
1. What is the CSS Grid Layout ?
If you’re new to layouts in CSS, the CSS Grid layout may seem strange to you.
Have you heard of Flexbox?
I like to view the CSS Grid layout as an older sibling (or parent) of Flexbox.
Handling Layouts in CSS have been difficult and crappy. Flexbox brought a bit of fresh air — but the CSS Grid is even better.
What we’ll Build.
You will learn to apply your 20% knowledge to building a clone of a responsive music app layout.
Part 1: The 10% you Need to Know — Basic Terminologies
Let’s take a look at the first things you absolutely have to know.
What is a Grid Container?
Every website, or application layout you make (or have seen) is essentially, boxes placed within certain defined boundaries.
In very simple terms, a grid is just “lines”. Horizontal and vertical lines that define the placement of other design elements.
You’ll be familiar with this if you use design software such as adobe photoshop or sketch.
In the context of the CSS Grid layout, A Grid container is the parent that contains all the items in the grid. The Grid container defines the initial placement of the grid lines, both vertical and horizontal.
What is a Grid Line?
Assume for a bit that you have a fully laid out grid like this:
The layout comprises a grid container with a number of perfectly laid out grid items (children elements within the grid)
Grid lines are the horizontal and vertical lines that divide the grid.
What is a Grid Cell?
A Grid cell is the smallest unit of area in a grid layout. It is any space bounded by four grid lines.
Grid Area
A grid area may be as small as the area contained within a grid cell (shown above). It may also be as large as all the cells within the grid.
In the image below, the area covered by the four cells is a grid area.
What is a Grid Track
I don’t like very technical definitions. So, a grid track may be seen as a fancy name for columns and (or) rows. It is the space between any two grid lines.
The image below show example grid tracks.
So, we’ve got the first part sorted out.
Part 2: The “Other” 10% you Need to Know — CSS Grid, Baby steps.
Now that you understand the basic terminologies, like an adventurous kid, let’s get kicking!
How do you Define a Grid?
Just like Flexbox, everything begins with a one-liner. display: grid
or display:inline-grid
for an inline version.
For example, to make a certain div
a grid container, do this:
div {
display: grid;
}
How do You Create Columns and Rows?
A grid without columns and rows is kinda pointless. To create columns and rows within a grid container, you use these two new css properties: grid-template-columns
and grid-template-rows
.
So how do you use these? Pretty simple.
grid-template-columns
defines the placement of the columns. grid-template-rows
defines the placement of the rows.
You pass in length values into these properties, and they create row and column tracks within the grid container.
See an example:
grid-template-columns: 100px 200px 300px
This will create 3 new columns within the grid container. The first with a length of 100px
, the other, 200px
and the last, 300px
.
grid-template-rows: 100px 200px 300px
This will create 3 new rows within the grid container. The extents are shown below
Now put these together, and you get a full grid — with rows and column defined.
grid-template-columns: 100px 200px 300px
grid-template-rows: 100px 200px 300px
Part 3: Time to Code — CSS Grid, Hands-on
Now let’s take baby steps to building a clone of the famous music app, catty music 😁
For speedy development, I would be using Codepen. Spin up a new project, and let’s get cracking.
How to Create the Basic Grid Setup for Catty Music
I believe you have a basic codepen project up and running now.
We will kick off with a very basic html
document.
<body>
<aside></aside>
<main></main>
<footer></footer>
</body>
There’s a bit of foresight involved in choosing this structure. You’ll understand very soon.
Now style the document.
body {
display: grid;
min-height: 100%
}
This will kick off the grid formatting context by making the body a grid-container
Now we can go on to define the rows and columns structure within the grid.
How to create the Rows and Columns for Catty Music
Creating the rows and columns is pretty easy.
The final design we are gunning for is this:
However, the initial grid setup we need is a grid of 2 rows and 2 columns.
Here are a few things to note about this Grid setup
Columns:
- The first column must have a fixed width — say, 50px
- The second column must fill the remaining width in the grid.
Rows:
3. The second row must have a fixed height — say, 100px
4. The first row must also fill the remaining height within the grid.
The lay-man’s solution.
If you’re NOT very experienced with CSS, you’re likely to write this:
body {
...
grid-template-rows: 100% 100px;
grid-template-columns: 50px 100%;
}
The problem with this is that you have accidentally created a grid whose width and height is a total of 100% + 50px
/ 100% + 100px
We want a total width and height of exactly 100%
So this approach is wrong.
The “smart ” person’s solution.
If you’ve got some experience with CSS under your belt, then you’re likely to do something much more smarter. Like this:
body {
...
grid-template-rows: calc(100% - 100px) 100px;
grid-template-columns: 50px calc(100%-50px)
This is pretty smart. But it’s got one problem — it isn’t very maintainable.
For example, If for some reasons you have to change any of the the fixed widths, then you must always change the calc definition.
The efficient Solution
Luckily, CSS Grid has a new unit that solves our problem elegantly. The fractional unit (fr)
The fractional unit solves the problem of automatically distributing space.
If you have three grid columns aligned as shown below, the fractional unit will automatically distribute the space equally.
If for some reason you add more elements — no worries. The fr
unit will equally redistribute the space .
Finally, if you have a fixed width element, then you can take up the remaining space with the fr
unit.
Here’s what I mean:
body {
...
grid-template-rows: 1fr 100px;
grid-template-columns: 50px 1fr;
And that is it — done!
If you’re still confused with fr
unit, please check out, the CSS Fractional Unit (Fr) In Approachable, plain Language. It only takes 3 minutes.
Naming and Positioning Items by Grid Areas
We explicitly created the grid system. Now, let’s put it to use.
The goal of this section is to learn to position grid items using grid areas.
If you recall from an earlier section, a grid area is any area bounded by 4 grid lines.
How do you start using grid areas?
The logical place to begin is naming grid areas.
Let me explain that.
Consider the code block below:
<div class="aside"></div><div class="main"></div><div class="footer"></div>
3 divs — simple. By the way, It is semantically better to use aside
main
and footer
tags. I’ll just keep things simple.
Now see this:
.main {
grid-area: content;
}.footer {
grid-area: footer;
}.aside {
grid-area: sidebar;
}
What is happening there?
If you write a bit of Javascript, or any programming language, then the concepts of variables isn’t new to you.
In Javascript, we could say:
var gridArea = "content"
What is done above is, save the string content
into the variable gridArea
What the CSS declarations above does is quite similar.
Every grid item can be assigned to an area within the grid container. Read that again.
Every grid item can be assigned to an area within the grid container
However, before doing that, it is imperative to attach the grid items to an area name. Like you assign variables in Javascript — sort of.
.main {
grid-area: content;
}.footer {
grid-area: footer;
}.aside {
grid-area: sidebar;
}
The code block above says, let the .main
class have an area name of content
. Let the .footer
class have an area name of footer
. Finally, let the aside
class have a grid name of sidebar
Now the grid items have all been assigned area names.
In programming, variables are set to be used elsewhere. Now let’s make use of the grid area names.
Grid area placement
A young man has a well baked cake. He has 3 children asking to give them some portions. Ideally, who shares the cake?
The young man!
The young man cuts out the areas and gives them to his children.
Here’s why I told that sweet story.
Like the cake, the entire grid area is owned by who?
The grid container!
Like the young man, the grid container has 3 children too .aside
.main
and .footer
Now the grid container gets to choose how the entire area portions are shared.
One more thing.
Because the children all have names, the young man may say, “hey Brian, here’s your portion”, or “hey Emma, have this”
It is easy to identify who owns what portion of the cake, by assigning the portions to a named individual. I have no cure for you if you live in a country where people go without names 😁
The grid items all have names! We did so using the grid-area
property.
Now, let’s share the cake!
The grid-template-areas property
Now the grid container must share the “cake”. Assign what area portions goes to who.
There are many ways to do what I am about to explain to you, but the grid-template-areas
property is the easiest to reason about. It is the bit you need to know for efficiency.
How does the grid-template-areas property work?
Take a look at the code below:
body {
grid-template-areas: "sidebar content"
"footer footer";
}
😳 what the heck is that ?
That my dear, is the grid-template-areas
property in action. There’s no need to get overwhelmed. In this section, I will explain how it works — in clear terms.
The grid-template-areas
property (what a long property name) provides a very visual structure of the grid.
Take a look at the code again:
body {
...
grid-template-areas: "sidebar content"
"footer footer";
}
Note that the entries in the property value are the names of the grid items!
sidebar
content
and footer
refer to the names of the grid items. The declaration above has succesfully shared the area with respect to the names of the grid items — brilliant!
The image above will help you understand how the area portions have been split.
The footer
takes the entire bottom area. The sidebar
and content
take first and second top areas respectively.
Awesome!
At this point here’s what we have:
body {
display: grid;
grid-template-columns: 40px 1fr;
grid-template-rows: 1fr 90px;
grid-template-areas: "sidebar content"
"footer footer";
}
The result of that is this:
I have added colors for visual aid. The red section represents the footer, the other two sections, the .main
section and .sidebar
.
Let’s Get Responsive — Redefining Grid Areas with Media Queries
The Grids areas you create within the parent grid container are not set in stone. The grid areas can be changed based off of the screen size of the user’s device.
The Image below shows what we aim to achieve on mobile displays.
For our specific use-case we will do some refactoring for a mobile first approach.
Mobile first is simply making your default styles those for mobile devices. Then you may go ahead to make changes for larger displays via media queries.
Tweak the current code you have now. Wrap the grid defining bit in a media query.
Like this:
@media only screen and (min-width: 600px) {
body {
grid-template-columns: 120px 1fr;
grid-template-areas: "sidebar content"
"footer footer";
}
}
You should leave the defaults excluded from the media query
body {
display: grid;
grid-template-rows: 1fr 50px;
}
Why do I have grid-template-rows: 1fr 50px
excluded from the media query?
This is because both mobile and desktop screens will have the same row definition. 2 rows.
However, on desktop devices, there’s a sidebar. The sidebar accounts for the 120px
in the grid-template-columns
definition. Howbeit, the sidebar is non-existent on mobile devices.
Thus, we will redefine the grid-template-column
declaration for mobile.
Now for mobile devices, we will leave this as the default styling. i.e not wrapped in any media query.
body {
grid-template-areas: "content"
"footer"
Pretty simple?
Let me explain.
The default flow (direction) of a Grid
The code block for mobile displays is easy.
body {
grid-template-areas: "content"
"footer"
However, note that there was no need to specify grid-template-columns
By default, a grid will align it’s children along rows.
So, the declaration above will align content
along a row, and footer
along another.
Below is the result of that — the sidebar hidden on mobile.
With the initial hurdle of understanding how grids work, and setting up a responsive grid, let’s finish up the app layout!
Placing Content within the Grid.
At the end of this section, we would have the Music app layout completed. The focus being, how to place and align content within grids.
Let’s get started.
1. The Sidebar
This looks like the easiest to start with. Let’s go for it.
The sidebar consists of 8 icons equally spaced out vertically accross the entire length of the sidebar.
Insert the icons, like this:
<div class="aside">
<i class="fa fa-bars"></i>
<i class="fa fa-home"></i>
<i class="fa fa-search"></i>
<i class="fa fa-volume-up"></i>
<i class="fa fa-user"></i>
<i class="fa fa-spotify"></i>
<i class="fa fa-cog"></i>
<i class="fa fa-soundcloud"></i>
</div>
Below is the result of that:
Also, hide the icons when on mobile. Show them when the app is visited on a larger screen. This is the mobile first approach.
.aside i {
display: none;
}@media only screen and (min-width:600px) {
.aside i {
display: block;
}
}
The icons are displayed, but poorly aligned.
Aligning the icons
The i
tags are inline elements — which explains why every 2 icons sit on one line.
Let’s fix the arrangement.
Grid items can be grids themselves. Why not
Step 1: Make the Sidebar a Grid Container
This will give access to using the grid’s alignment features.
Since the sidebar is only seen on larger screens, do not forget to wrap this in the media query.
@media only screen and (min-width:600px) {
.aside {
display: grid;
}
.aside i {
border: 1px solid red;
}
}
I have gone ahead to add borders to each icon — so they are visually distinguishable.
What’s happening there?
We have NOT set up any rows or columns within the sidebar. But we have the icons laid out fairly well. The grid auto placement algorithm has set in.
This is got to do with the default placement of items in a grid — along a row. Also, the grid items are arranged to take up the space of the grid container, as needed.
Here comes the sweet sauce.
A grid may align it’s items using any of justify-items
or align-items.
justify-items
will align the items along the row
axis. In most cases, row is pretty much synonymous with the horizontal direction.
align-items
will align the items along the column
axis. In most cases, column is also synonymous with the vertical direction.
Apply this to the sidebar, and we have perfectly laid out icons.
.aside {
...
justify-items: center;
align-items: center;
}
Still confused, watch the changes in the sidebar items as I type.
Now we have perfectly laid out icons within the sidebar.
A few other values justify-items
and align-items
can take include:
- stretch
- start
- end
- center
If you’ve worked with Flexbox, these should be familiar.
We’ll proceed to placing more content into the current design.
Target the main section, the dark blue section in the image above. Place two div
within:
<div class="main">
<div class="main__header"></div>
<div class="main__body"></div>
</div>
NB:
main__header
will house the music art and playbacks:
2. main__body
will house the details:
In this section we will focus on main__header
First off, add the required html
<div class="main__header">
<div class="img">
<img src="http://bit.ly/2sc2NJd"/>
</div>
<section class="details">
<div>
<p>CattyBoard Top 100 Single Charts (11.06.36)</p>
<p class="sm--hide">Unknown Artist</p>
<p class="sm--hide">2016 . Charts . 100 songs</p>
</div>
<div>
<i class="fa fa-play"> Play all</i>
<i class="fa fa-plus"> Add to</i>
<i class="fa fa-ellipsis-h"> More</i>
</div>
</section>
</div>
Note the way the document is structured.
main__header
has two direct children. A div
that contains an image, and a section
that contains album details, .details
The result of the addition above is this rather ugly image:
Let’s make this pretty.
What we need is a grid that aligns its children appropriately.
Let’s make use of your new knowledge of grid areas.
First step, define the grid areas:
.main__header > .img {
grid-area: img;
}
.main__header > .details {
grid-area: dtls;
}
The div
containing the image has been named img
The section containing the album details has been named dtls
Now, define the grid itself:
.main__header {
display: grid;
grid-template-areas: "img"
"dtls";
}
.main__header
sets a grid formatting context. The areas have also been aligned to stack vertically on another. img
first, then dtls
This is because we are working with a mobile first approach. Good.
At this point, nothing much’s changed.
This is NOT the view we want on mobile.
For mobile screens, the items should be aligned to the center. Fix that.
@media screen and (max-width: 600px) {
.main__header {
justify-items: center;
}
}
Now the grid items will be positioned to the center of the grid (along the row)
Make the texts in .details
align to the center:
@media screen and (max-width: 600px) {
.main__header > .details {
text-align: center;
}
}
Pretty close to the end goal. Just a few more tweaks.
The paragraphs with the texts, unknown artist, and 2016 . Charts. 100 songs. should be hidden on mobile. The image should be smaller too.
@media screen and (max-width: 600px) {
.sm--hide {
display: none;
}
.img > img {
width: 150px
}
}
Every class .sm--hide
will be hidden on mobile. Just add this class to the desired element.
Here’s how:
<p class="sm--hide">Unknown Artist</p>
<p class="sm--hide">2016 . Charts . 100 songs</p>
And we have this:
Having sorted out the view on mobile, let’s fix that for larger screens.
Back to the parent grid.
For larger screens, we need a 2 column grid. The areas should be split like this:
@media only screen and (min-width:600px) {
.main__header {
grid-template-columns: 250px 1fr;
grid-template-areas: "img dtls"
}
}
I’m sure you understand what’s going on there.
The grid has been redefined to have two columns. One fixed at 250px
and the other to fill the remaining space.
Our current progress lives here.
Part 4: Making CSS Grid work with Flexbox
In this part, you’ll learn to make Flexbox and Grid work together — peacefully.
These two technologies have changed how layouts in CSS are treated. It is efficient ot use both technologies where possible.
Let’s delve in.
For the section housing the music details, we will use flexbox.
How do you know where to use Flexbox?
As a general rule of thumb, it is appropriate to use Grid to layout the overall page layout, and Flexbox for inner UI components.
A grid item can be a flex container. A flex item can also be a grid container. The latter is frequently used though.
I assume you have a good grasp of flexbox.
As always, begin with the html
Below is a div
, with a list of songs. The list of songs have paragraphs containing the name of the song, artiste, duration of the song and “catty cloud sync”.
<div class="main__body">
<div>
<p>1. One Dance</p>
<p>Crake feat CatKid & Cyla</p>
<p>2:54</p>
<p><span>CATTY CLOUD SYNC</span></p>
</div>
<div>
<p>2. Panda</p>
<p>Cattee</p>
<p>4:06</p>
<p><span>CATTY CLOUD SYNC</span></p>
</div>
<div>
<p>3. Can't Stop the Feeling!</p>
<p>Catin Cimberlake</p>
<p>3:56</p>
<p><span>CATTY CLOUD SYNC</span></p>
</div>
<div>
<p>4. Work From Home</p>
<p>Cat Harmony feat Colla</p>
<p>3:34</p>
<p><span>CATTY CLOUD SYNC</span></p>
</div>
</div>
Here’s what we’ve got:
main__body
is a grid item. We could make it a flex container if that was useful.
For our use case, each direct div
child of main__body
needs to be flex container. This is the div
that contains the name of the song, artiste, duration of the song and “catty cloud sync”.
.main__body > div {
display:flex;
}
Now split the width amongst the child elements:
.main__body > div p{
flex: 0 0 25%;
}
You’ll agree with me that at this point, the essentials of the layout is done. Yes, ✅
However, I have gone ahead to make a few cosmetic changes.
You may view the result of that here
You’ll notice that I have left the footer blank. That’s supposed to be an exercise for you. My advice is to use flexbox. This will strengthen your understanding of getting both technologies to work together. Go ahead and make the grid item, footer
a flex container.
If you need some cues, check out catty music built completely with flexbox.
With just a few grid properties, you have built a real world layout. That’s pretty impressive. You’ve also learned the invaluable skill of making the CSS Grid layout work with Flexbox too.
Want to become Pro?
Download my free CSS Grid cheat sheet, and also get two quality interactive Flexbox courses for free!