Back to the old days of creating web pages, we used HTML tables to create page layout, and then we started to use some CSS properties like floats combined with clearfix, and box-sizing. Another option is to use a CSS framework to help us create the complex layouts we need.
As Web Applications becomes more and more complex in different domains including layouts and responsive design, we need as web developers a more natural, and native way to do complex layouts easily without any hacks and workarounds. Fortunately an exciting new solution for creating layouts comes with the CSS Grid Layout Module.
In this introduction we will discover the new Grid Module, the current browser support, and how it works with some practical examples.
The core idea behind the Grid Layout is to divide the web page into columns and rows, and then we have the ability to position and size the building block elements based on the rows and columns we have created in terms of size, position and layer.
The Grid also gives us a flexible way to change the layout elements position with only CSS without any change to HTML, which could be used with Media Queries to change the layout at different breakpoints.
Before we can dive more into the Grid, we need to talk about the current browser support, and how we can enable it in the current browsers.
Since the first proposal of the Grid developed by Microsoft, Internet Explorer 10 shipped with a -ms
prefixed implementation. If we take a look at the image above, or Can I Use report, we can see that both Internet Explorer 11, and Edge are also supported. In other browsers the Grid Layout is not supported by default, but we can enable it as we will see next.
Navigate to chrome://flags
URL, look for Enable experimental Web Platform features
flag, enable it, then you will be asked to relaunch Chrome.
It's recommended to use either Chrome or Opera with the article examples or your own next experimentations, as the Blink engine has the most updated implementations.
Navigate to about:config
URL, search for layout.css.grid.enabled
flag, then double click or press enter to toggle it to true
for activation.
A Polyfill is also available to provide a working implementation of the Grid Module for current browsers.
Let's start with an example to see the power of the Grid Module, and then we will explain some new concepts in more details.
Imagine we want to create an application for Twitter with four full height columns layout (Tweets, Replies, Search, and Messages), something abstracted and similar to the screenshot below.
Application HTML will be:
<div class='app-layout'>
<div class='tweets'>Tweets</div>
<div class='replies'>Replies</div>
<div class='search'>Search</div>
<div class='messages'>Messages</div>
</div>
Then we will apply our CSS code on the .app-layout
container element:
.app-layout {
display: grid; // 1
grid-template-columns: 1fr 1fr 1fr 1fr; // 2
grid-template-rows: 100vh; // 3
}
Demo: 4 columns layout using CSS Grid
Here is the explanation of what we've done in the previous CSS code:
- Set the display property value to
grid
. - Divide the container element into four columns, each column is
1fr
(one fraction) of the free space within the grid container. - Create one row and set the height to be
100vh
(full viewport height).
The new Grid Module added a new value to the display
property which is grid
. The grid
property is responsible for setting the .app-layout
element to be a grid container, which also establishes a new grid formatting context for its contents. This property is required to start using the Grid.
The grid-template-columns
specifies the width of each grid column within the Grid, and in our case it divides the .app-layout
container to four columns, each one is 1fr
(25%) of the available space.
The grid-template-rows
specifies the height of each grid row in the Grid, and in our example we only created one row to be 100vh
.
If wee need to create a layout with two columns, and two rows as:
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50vh 50vh;
}
Demo: 4 boxes layout using CSS Grid
We can also achieve the above example only on small screens by wrapping the code inside a media query. This opens a great opportunity for us to customize the layout differently in different viewports. For example, we can create the previous layout only on a viewport less than 1024px
as:
@media screen and (max-width: 1024px) {
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 50vh 50vh;
}
}
Demo: 4 boxes layout using CSS Grid - Responsive
After we have did our first example, there are some new concepts that we need to know for a better understanding the new Module. There are a lot of new concepts, we will only take a look at a few of them.
Grid Item
Grid items are the child elements of the grid container, like .tweets
, and .replies
elements.
Grid Lines
A Grid Line is a line exist on either side of a column or a row. There are two sets of grid lines: one set defining columns (vertical axis), and another set defining rows (horizontal axis).
From the above screenshot that represents the first example, we did four columns each one is 1fr
which will give us five vertical lines, and we did one row, which will give us two horizontal lines.
Let's see how we can position a gird item inside the grid container in the two ways:
We can refer to the exact line number by using new properties like grid-column-start
, and grid-column-end
, we then give theses properties the start line and the end line numbers.
From the previous example, this is how the browser position the elements by default for us, and we can mimic the default columns positions as:
.tweets {
grid-column-start: 1;
grid-column-end: 2;
grid-row: 1;
}
.replies {
grid-column-start: 2;
grid-column-end: 3;
grid-row: 1;
}
.search {
grid-column-start: 3;
grid-column-end: 4;
grid-row: 1;
}
.messages {
grid-column-start: 4;
grid-column-end: 5;
grid-row: 1;
}
Let's take the .tweet
column and see how the position is working:
- Position the child element from the first vertical line to the left.
- End the element position by the second vertical line.
- Position the element inside the whole row.
Let's change this by changing the order of elements with different positions, so our elements order will be: .search
, .replies
, .messages
, and .tweets
.
.search {
grid-column-start: 1;
grid-column-end: 2;
grid-row: 1;
}
.replies {
grid-column-start: 2;
grid-column-end: 3;
grid-row: 1;
}
.messages {
grid-column-start: 3;
grid-column-end: 4;
grid-row: 1;
}
.tweets {
grid-column-start: 4;
grid-column-end: 5;
grid-row: 1;
}
Or simply we can use the grid-column
shortcut to set the start, and end lines as:
.search {
grid-column: 1 / 2;
grid-row: 1;
}
.replies {
grid-column: 2 / 3;
grid-row: 1;
}
.messages {
grid-column: 3 / 4;
grid-row: 1;
}
.tweets {
grid-column: 4 / 5;
grid-row: 1;
}
Demo: 4 columns layout using CSS Grid - Search First
We have changed the layout structure with only CSS, and the markup is still as it is without any changes, this is a huge advantage of using the new Grid Module.
We can rearrange the layout of elements independent of their source order, so we can achieve the desired layout in different screen size, orientation. This is very useful because we will separate the markup from CSS and change everything from CSS without editing HTML anymore.
A grid area is the logical space used to layout one or more grid items, we can name a grid area explicitly using the grid-template-areas
property, then we can place a grid item into a specific area using the grid-area
property.
To make the concept more clear, let's redo our four columns example, with columns reorder as search
column comes first.
.app-layout {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 100vh;
// We divided the grid container into four named grid areas, each one for a column
grid-template-areas: "search replies messages tweets";
}
The next step is to position each grid item into a named area:
.search { grid-area: search; }
.replies { grid-area: replies; }
.messages { grid-area: messages; }
.tweets { grid-area: tweets; }
Demo: 4 columns layout using CSS Grid - grid-area
What about using the Grid Module to implement a more complex example, what about creating the building blocks of the Slack application layout.
Since we are talking about layouts, we will abstract and simplify the Slack design to the building blocks represented in the grid, something like this:
From this layout we will create three vertical columns, and three horizontal rows, and we can visualize it as:
We will start with the layout HTML:
<div class='app-layout'>
<div class='teams'>Teams</div>
<div class='channels'>Channels</div>
<div class='header'>Header</div>
<div class='messages'>
<ul class='message-list'>
<li></li>
<li></li>
</ul>
</div>
<div class='input'>
<input type='text' placeholder='CSS Grid Layout Module'>
</div>
</div>
And the CSS:
.app-layout {
display: grid;
height: 100vh;
// Create three columns:
// First columns is: 100px width
// Second columns is: 250px width
// Third columns is: the available space
grid-template-columns: 100px 250px 1fr;
// Create three rows
// First row: auto height
// Second row: the available space
// Third row: auto height
grid-template-rows: auto 1fr auto;
}
.teams {
grid-column: 1;
grid-row: 1 / 4;
}
.channels {
grid-column: 2;
grid-row: 1 / 4;
}
.header {
grid-column: 3;
grid-row: 1;
}
.messages {
grid-column: 3;
grid-row: 2;
}
.input {
grid-column: 3;
grid-row: 3;
}
Demo: Slack layout using CSS Grid
Using Named Areas
.app-layout {
display: grid;
height: 100vh;
grid-template-columns: 100px 250px 1fr;
grid-template-rows: auto 1fr auto;
// Create three columns and three rows template, with nine named grid areas
// The teams area spans the first column and the three rows
// The channels area spans the first column and the three rows
// The header area at the third column and the first row
// The messages area at the third column and the second row
// The input area at the third column and the third row
grid-template-areas: "teams channels header"
"teams channels messages"
"teams channels input";
}
.teams {
grid-area: teams;
}
.channels {
grid-area: channels;
}
.header {
grid-area: header;
}
.messages {
grid-area: messages;
}
.input {
grid-area: input;
}
Demo: Slack layout using CSS Grid - Named Areas
In a small screen we can position all child elements on top of each other, this will require us to modify the columns, rows, and areas like this:
@media screen and (max-width: 1024px) {
.app-layout {
grid-template-columns: 100%;
grid-template-rows: auto auto auto 1fr auto;
grid-template-areas: "header"
"teams"
"channels"
"messages"
"input";
}
}
Demo: Slack layout using CSS Grid - Responsive Named Areas
Since many of us have used Flexbox before, one question would come to mind to say: When can I user Flexbox, and when can I use the Grid Module?
There are two good answers I read about the difference, and the context in which we can use any of them.
Flexbox is appropriate for many layouts, and a lot of "page component" elements, as most of them are fundamentally linear. Grid is appropriate for overall page layout, and for complicated page components which aren't linear in their design.
The two can be composed arbitrarily, so once they're both widely supported, I believe most pages will be composed of an outer grid for the overall layout, a mix of nested flexboxes and grid for the components of the page, and finally block/inline/table layout at the "leaves" of the page, where the text and content live.
Grid Layout vs Flexbox by: Tab Atkins
Grid Layout for the main page structure of rows and columns.
Flexbox for navigation, UI elements, anything you could linearize.
Flexbox and Grid Layout by: Rachel Andrew
We have not covered all the Module concepts and syntax, so I recommend you to discover and read from theses great resources to get deeper into the Grid.
- CSS Grid Layout Module - W3C
- CSS Grid Layout Examples
- Grid by Example
- The future of layout with CSS: Grid Layouts
- Follow Rachel Andrew for new updates, and resources. She is doing a great work regarding the Grid.
As we’ve seen, the upcoming CSS Grid Layout Model is awesome in different areas like: less code we have to write, the power of changing the layout only with CSS, responsive design, and this enables us making complex layouts in a new and native way, and it will change the way we create layout for the web.