News

Get started with CSS Grid layouts now

Explore how to use CSS Grid, a new W3 spec that lets you easily build complex and beautiful layouts with simple code

CSSGridMain

Explore how to use CSS Grid, a new W3 spec that lets you easily build complex and beautiful layouts with simple code

CSSGridMain

The web has never really had a true layout system. We hacked together tables, floats, absolute positioning and flexboxes, but we have had to bend our content backwards and cram in all sorts of non-semantic junk in order to end up with something resembling what we want. It’s frustrating that it takes dozens (if not hundreds) of lines of CSS, and an insane amount of classes and IDs in order to do some of the most common and straightforward layouts on the web. CSS Grid is a new standard already shipping in IE and Edge, and available behind flags and prefixes in Firefox, Chrome and WebKit Nightly, that saves us from all of that. It lets you define your page, or sections of the page, as a collection of vertical and horizontal lines that creates cells (similar to a table), which you can then place any of its children into arbitrarily. This means that with a single line of CSS you can completely rearrange the content without changing the document’s source order! Responsive designs get that much easier. You don’t need any wrapper or container divs – just the content, the way the web was meant to be.


GET THE CODE FOR THIS TUTORIAL

1. Set up your container

There is a single requirement to using CSS Grid, and that is to set your containing element to display: grid. Once you have done that, the children elements can be positioned (either by Grid’s default positioning or – more likely – via a few additional lines of CSS).

2. Change the flow

By default, all of your child elements are now aligned to a single column, multirow grid. You have the ability to convert this to a single-row, multicolumn grid by changing the grid-autoflow value.

.container {
display: grid;
/* now we will get one long column
with as many columns as children */
grid-auto-flow: column;
}

3. Define the grid

More than likely we want more than one row or column, and so can explicitly define both. You can use any CSS length unit in your definition. Begin with a simple full-height, three-column layout. It will have fixed width sidebars, with the centre column taking up the space.

4. Align to the grid

Now that our grid is defined, we can align our content to it. We do this with line-based placement – basically we say which lines we want our content to be between and where a line is defined as one of the columns or rows we just marked up on our container, both start with 1.

.leftColumn {
grid-column-start: 1;
grid-row-start: 1
}

5. Figure out the lines

Line-based placement can quickly become confusing, but it is actually pretty straightforward. Grid-column-start: 1 means the start first most column, 2 means the end of that same column, 3 the start of the next one, and so on. Rows work the same way, just vertically.

6. Expand our cells

Grids wouldn’t be very useful if they were only able to span a single cell. That is why it is easy to make them take up as many or as few columns and rows as you wish. Just include a grid-column-end/grid-row-end as needed. The rules work exactly the same as the -start.

.leftColumn {
/*start at the beginning of the grid*/
grid-column-start: 1;
/*expand past the gutter, to the end
of the main content area*/
grid-column-end: 4;
}

7. Expand our cells

You may not care where the element is specifically on the grid, just that it should take up a certain number of columns. The new grid specific span keyword will do just the trick! Set your grid-column/grid-row value to ‘span N’ and you will have it.

.leftColumn {
/*start at the beginning of the grid*/
grid-column-start: 1;
/*expand past the gutter, to the end
of the main content area, or 3 lines*/
span: 3;
}

8. Use named lines

You can simplify your layout even more by using named lines. The only difference between what this and what we have already done is that you can include a name in parenthesis in-between the column or row size declaration. You can then use these names instead of the numbers we used before!

.container {
grid-template-columns:
(sideStart) 350px
(sideEnd) 50px
(mainStart) 1fr (mainEnd)
}
.leftColumn {
grid-column: sideStart / sideEnd
}

9. Named lines aren’t unique

The names you give lines are like classes, they can be reused to represent multiple repeated lines. If you want to name every gutter as (gutter) you will need to change how you reference the grid lines in your placement.

.container {
grid-template-columns: repeat(4,
(col) 75px (gutter) 20px
)
}
.main {
/* start at the second named col,
and end at the 6th named gutter */
grid-column: col 2 / span gutter 6
}

10. Simplify the templates

You may have noticed that anything beyond simple column and row templates will quickly get very unwieldy. You can quickly get the same boilerplate code over and over again. Luckily, there is a new helper function called ‘repeat’ which saves a bunch of space (and bytes!)

.container {
grid-template-columns:
350px 50px 350px 50px 350px 50px;
grid-template-columns:
repeat(3, 350px 50px)
}

11. Simplify the positioning

You also have the ability to keep your positioning rules clean with the shorthand way of defining grid-column/row-start and grid-column/row-end. Just use grid-column/row, followed by the start and end values, separated by a slash.

.leftColumn {
/* equal to
grid-column-start: 1
grid-column-end: 4
*/
grid-column: 1 / 4;
grid-row: 2 / 4;}

12. Be more terse with grid-area

You can use even fewer rules by using grid-area. With it, you are able to define the column start and end, and the row start and end with a single rule. You just use the same numbers as before, in the order of row start, column start, row end and column end.

.leftColumn {
/* equal to
grid-row-start: 2
grid-column-start: 1
grid-row-end: 4
grid-column-end: 3
/*
grid-area: 2 / 1 / 4 / 3;}

13. Eat up the free space

You may have noticed that we used a new CSS unit – fr. This is a fractional unit, a new unit specifically for grid that represents a fraction of the space remaining container. What that means is if the grid is 100px wide with two children, and the first child is a fixed width of 72px, then 1fr equals 100-72, or 28px.

.container {
display: grid;
width: 100px
grid-template-columns: 72px 1fr;}
.leftColumn { /* the first, so 72px */ }
.rightColumn { /* the second, so 1fr
or 28px wide */ }

14. Use 2fr instead

You might be wondering what happens if you use 2fr, instead of 1fr or if you use multiple frs in a single template. The results are very similar to flex-grow from flexbox – ie if you used 2fr 1fr then the first item would take up two-thirds, and the second would take up a third.

.container {
width: 200px;
grid-template-columns:
50px /* explcitly 50px side */
/* there are 4fr declared, so the
rest of the 150px is split into 4 */
1fr /* 1/4 of 150, or 37.5px */
2fr /* 2/4 of 150, or 75px */
1fr /* 1/4 of 150, or 37.5px */}

15. Source order !== display order

One of the best things about CSS Grid is that since you don’t need weird wrapper elements, you can quickly and easily rearrange content when you are creating a responsive design simply by changing the grid-column and row values.

.container {
display: grid;
grid-template-columns: 250px 1fr 250px;}
.main { grid-column: 2 / 4 }
@media (min-width: 500px) {
.container {
grid-template-columns: auto;}}

16. Use grid-area names

It can quickly becoming overwhelming trying to remember the grid order, and as a result the spec includes the concept of grid-area names. These act as a sort of variable reference to that grid element, and can let you easily refer to it in other sections of your CSS.

.header {
grid-area: header;}
.sidebar {
grid-area: sidebar;}
.main {
grid-area: main;
}

17. Rearrange by name

We saw that you can easily move your grid placements around inside of media queries by changing the template values, you can also accomplish this in a more readable way by using grid-template-areas and the grid-area names that we just set up. Just list the names in the order you want them to appear.

.container {
grid-template-columns: auto;
grid-template-rows: auto;
grid-template-areas:
"header"
"sidebar"
"main"}

18. Get more complexity

Step 17 shows how simple it is to define a single-column grid. But what if you want something a bit more complex? You can include multiple grid-areas per line by using multiple names per set of quotes, and then stretch it over several rows by referencing it in subsequent quoted values.

.container {
grid-template-columns: 250px 250px;
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer"
}

19. Mind the gaps

You will almost certainly want to not have your content pressed up against one another. You can still use content gutters with this technique by using a . to represent the unnamed grid area.

.container {
grid-template-columns: 250px 50px 250px;
grid-template-areas:
/* the header takes up all 3 columns */
". . header"
/* sidebar, gutter, then main */
"sidebar . main"
"sidebar . footer"
}

20. Align our items

A number of rules from flexbox can be used out of the tin with grid. Justify-self, justify-items, justify-content as well as align-self, align-items and align-content can all be used directly on the relevant grid parts just as you would with flexbox! It makes centring and justification a breeze.

.container {
grid-template-columns: 350px 350px;
/*center children horizontally*/
justify-items: center;
/*place children at the vertical end*/
align-items: end;
}

21. Look to the future

The grid spec has changed quite a bit since it was introduced in IE10. We’ve covered quite a bit of it, but one of the most exciting features that we didn’t touch is subgrids – the ability to turn one of the child elements into a grid itself. Web Components and page layouts will never be the same!


GET THE LATEST ISSUE OF WEB DESIGNER NOW


×