Metro: Introduction to CSS 3 Grid Layout

The purpose of this blog post is to provide you with a quick introduction to the new W3C CSS 3 Grid Layout standard. You can use CSS Grid Layout in Metro style applications written with JavaScript to lay out the content of an HTML page. CSS Grid Layout provides you with all of the benefits of using HTML tables for layout without requiring you to actually use any HTML table elements.

Doing Page Layouts without Tables

Back in the 1990’s, if you wanted to create a fancy website, then you would use HTML tables for layout. For example, if you wanted to create a standard three-column page layout then you would create an HTML table with three columns like this:

<table height="100%">
<tr>
  <td valign="top" width="300px" bgcolor="red">
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column
  </td>
  <td valign="top" bgcolor="green">
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column
  </td>
  <td valign="top" width="300px" bgcolor="blue">
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column
  </td>
</tr>
</table>

When the table above gets rendered out to a browser, you end up with the following three-column layout:

clip_image002

The width of the left and right columns is fixed – the width of the middle column expands or contracts depending on the width of the browser.

Sometime around the year 2005, everyone decided that using tables for layout was a bad idea. Instead of using tables for layout — it was collectively decided by the spirit of the Web — you should use Cascading Style Sheets instead.

Why is using HTML tables for layout bad? Using tables for layout breaks the semantics of the TABLE element. A TABLE element should be used only for displaying tabular information such as train schedules or moon phases. Using tables for layout is bad for accessibility (The Web Content Accessibility Guidelines 1.0 is explicit about this) and using tables for layout is bad for separating content from layout (see http://CSSZenGarden.com).

Post 2005, anyone who used HTML tables for layout were encouraged to hold their heads down in shame.

That’s all well and good, but the problem with using CSS for layout is that it can be more difficult to work with CSS than HTML tables. For example, to achieve a standard three-column layout, you either need to use absolute positioning or floats. Here’s a three-column layout with floats:

<style type="text/css">
#container {
  min-width: 800px;
}

#leftColumn {
  float: left;
  width: 300px;
  height: 100%;
  background-color:red;
}

#middleColumn {
  background-color:green;
  height: 100%;
}


#rightColumn {
  float: right;
  width: 300px;
  height: 100%;
  background-color:blue;
}
</style>


<div id="container">
  <div id="rightColumn">
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column
  </div>
  <div id="leftColumn">
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column
  </div>
  <div id="middleColumn">
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column
  </div>
</div>

The page above contains four DIV elements: a container DIV which contains a leftColumn, middleColumn, and rightColumn DIV. The leftColumn DIV element is floated to the left and the rightColumn DIV element is floated to the right. Notice that the rightColumn DIV appears in the page before the middleColumn DIV – this unintuitive ordering is necessary to get the floats to work correctly (see http://stackoverflow.com/questions/533607/css-three-column-layout-problem).

The page above (almost) works with the most recent versions of most browsers. For example, you get the correct three-column layout in both Firefox and Chrome:

clip_image004

And the layout mostly works with Internet Explorer 9 except for the fact that for some strange reason the min-width doesn’t work so when you shrink the width of your browser, you can get the following unwanted layout:

clip_image006

Notice how the middle column (the green column) bleeds to the left and right.

People have solved these issues with more complicated CSS. For example, see:

http://matthewjamestaylor.com/blog/holy-grail-no-quirks-mode.htm

But, at this point, no one could argue that using CSS is easier or more intuitive than tables. It takes work to get a layout with CSS and we know that we could achieve the same layout more easily using HTML tables.

Using CSS Grid Layout

CSS Grid Layout is a new W3C standard which provides you with all of the benefits of using HTML tables for layout without the disadvantage of using an HTML TABLE element. In other words, CSS Grid Layout enables you to perform table layouts using pure Cascading Style Sheets. The CSS Grid Layout standard is still in a “Working Draft” state (it is not finalized) and it is located here:

http://www.w3.org/TR/css3-grid-layout/

The CSS Grid Layout standard is only supported by Internet Explorer 10 and there are no signs that any browser other than Internet Explorer will support this standard in the near future. This means that it is only practical to take advantage of CSS Grid Layout when building Metro style applications with JavaScript.

Here’s how you can create a standard three-column layout using a CSS Grid Layout:

<!DOCTYPE html>
<html>
<head>

<style type="text/css">

html, body, #container {
  height: 100%;
  padding: 0px;
  margin: 0px;
}

#container {
  display: -ms-grid;
  -ms-grid-columns: 300px auto 300px;
  -ms-grid-rows: 100%;
}

#leftColumn {
  -ms-grid-column: 1;
  background-color:red;
}

#middleColumn {
  -ms-grid-column: 2;
  background-color:green;
}


#rightColumn {
  -ms-grid-column: 3;
  background-color:blue;
}
</style>
</head>
<body>

<div id="container">
  <div id="leftColumn">
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column
  </div>
  <div id="middleColumn">
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column
  </div>
  <div id="rightColumn">
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column
  </div>
</div>

</body>
</html>

When the page above is rendered in Internet Explorer 10, you get a standard three-column layout:

clip_image008

The page above contains four DIV elements: a container DIV which contains a leftColumn DIV, middleColumn DIV, and rightColumn DIV.

The container DIV is set to Grid display mode with the following CSS rule:

#container {
  display: -ms-grid;
  -ms-grid-columns: 300px auto 300px;
  -ms-grid-rows: 100%;
}

The display property is set to the value “-ms-grid”. This property causes the container DIV to lay out its child elements in a grid.

(Notice that you use “-ms-grid” instead of “grid”. The “-ms-“ prefix is used because the CSS Grid Layout standard is still preliminary. This implementation only works with IE10 and it might change before the final release.)

The grid columns and rows are defined with the “-ms-grid-columns” and “-ms-grid-rows” properties. The style rule above creates a grid with three columns and one row. The left and right columns are fixed sized at 300 pixels. The middle column sizes automatically depending on the remaining space available.

The leftColumn, middleColumn, and rightColumn DIVs are positioned within the container grid element with the following CSS rules:

#leftColumn {
  -ms-grid-column: 1;
  background-color:red;
}

#middleColumn {
  -ms-grid-column: 2;
  background-color:green;
}


#rightColumn {
  -ms-grid-column: 3;
  background-color:blue;
}

The “-ms-grid-column” property is used to specify the column associated with the element selected by the style sheet selector. The leftColumn DIV is positioned in the first grid column, the middleColumn DIV is positioned in the second grid column, and the rightColumn DIV is positioned in the third grid column.

I find using CSS Grid Layout to be just as intuitive as using an HTML table for layout. You define your columns and rows and then you position different elements within these columns and rows. Very straightforward.

Creating Multiple Columns and Rows

In the previous section, we created a super simple three-column layout. This layout contained only a single row. In this section, let’s create a slightly more complicated layout which contains more than one row:

clip_image010

The following page contains a header row, a content row, and a footer row. The content row contains three columns:

<!DOCTYPE html>
<html>
<head>

<style type="text/css">

html, body, #container {
  height: 100%;
  padding: 0px;
  margin: 0px;
}

#container {
  display: -ms-grid;
  -ms-grid-columns: 300px auto 300px;
  -ms-grid-rows: 100px 1fr 100px;
}

#header {
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
  -ms-grid-row: 1;
  background-color: yellow;
}

#leftColumn {
  -ms-grid-column: 1;
  -ms-grid-row: 2;
  background-color:red;
}

#middleColumn {
  -ms-grid-column: 2;
  -ms-grid-row: 2;
  background-color:green;
}

#rightColumn {
  -ms-grid-column: 3;
  -ms-grid-row: 2;
  background-color:blue;
}

#footer {
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
  -ms-grid-row: 3;
  background-color: orange;
}


</style>
</head>
<body>

<div id="container">
  <div id="header">
    Header, Header, Header
  </div>

  <div id="leftColumn">
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column,
    Left Column, Left Column, Left Column
  </div>
  <div id="middleColumn">
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column,
    Middle Column, Middle Column, Middle Column
  </div>
  <div id="rightColumn">
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column,
    Right Column, Right Column, Right Column
  </div>
  <div id="footer">
    Footer, Footer, Footer
  </div>
</div>

</body>
</html>

In the page above, the grid layout is created with the following rule which creates a grid with three rows and three columns:

#container {
  display: -ms-grid;
  -ms-grid-columns: 300px auto 300px;
  -ms-grid-rows: 100px 1fr 100px;
}

The header is created with the following rule:

#header {
  -ms-grid-column: 1;
  -ms-grid-column-span: 3;
  -ms-grid-row: 1;
  background-color: yellow;
}

The header is positioned in column 1 and row 1. Furthermore, notice that the “-ms-grid-column-span” property is used to span the header across three columns.

CSS Grid Layout and Fractional Units

When you use CSS Grid Layout, you can take advantage of fractional units. Fractional units provide you with an easy way of dividing up remaining space in a page.

Imagine, for example, that you want to create a three-column page layout. You want the size of the first column to be fixed at 200 pixels and you want to divide the remaining space among the remaining three columns. The width of the second column is equal to the combined width of the third and fourth columns.

clip_image012

The following CSS rule creates four columns with the desired widths:

#container {
  display: -ms-grid;
  -ms-grid-columns: 200px 2fr 1fr 1fr;
  -ms-grid-rows: 1fr;
}

The fr unit represents a fraction. The grid above contains four columns. The second column is two times the size (2fr) of the third (1fr) and fourth (1fr) columns. When you use the fractional unit, the remaining space is divided up using fractional amounts.

Notice that the single row is set to a height of 1fr. The single grid row gobbles up the entire vertical space.

Here’s the entire HTML page:

<!DOCTYPE html>
<html>
<head>

<style type="text/css">

html, body, #container {
  height: 100%;
  padding: 0px;
  margin: 0px;
}

#container {
  display: -ms-grid;
  -ms-grid-columns: 200px 2fr 1fr 1fr;
  -ms-grid-rows: 1fr;
}

#firstColumn {
  -ms-grid-column: 1;
  background-color:red;
}

#secondColumn {
  -ms-grid-column: 2;
  background-color:green;
}


#thirdColumn {
  -ms-grid-column: 3;
  background-color:blue;
}

#fourthColumn {
  -ms-grid-column: 4;
  background-color:orange;
}


</style>
</head>
<body>

<div id="container">
  <div id="firstColumn">
  First Column, First Column, First Column
  </div>
  <div id="secondColumn">
  Second Column, Second Column, Second Column
  </div>
  <div id="thirdColumn">
  Third Column, Third Column, Third Column
  </div>
  <div id="fourthColumn">
  Fourth Column, Fourth Column, Fourth Column
  </div>
</div>

</body>
</html>

 

Summary

There is more in the CSS 3 Grid Layout standard than discussed in this blog post. My goal was to describe the basics. If you want to learn more than you can read through the entire standard at http://www.w3.org/TR/css3-grid-layout/

In this blog post, I described some of the difficulties that you might encounter when attempting to replace HTML tables with Cascading Style Sheets when laying out a web page. I explained how you can take advantage of the CSS 3 Grid Layout standard to avoid these problems when building Metro style applications using JavaScript. CSS 3 Grid Layout provides you with all of the benefits of using HTML tables for laying out a page without requiring you to use HTML table elements.

ASP.NET 5/MVC 6 Training

Learn MVC 6 from Stephen Walther. We fly to you!
Learn More

Discussion

  1. Mike says:

    Once has to face it, Metro is horrendous.

  2. John says:

    Interesting look at CSS3 grids, but I think I’d rather write traditional CSS once and have something that is usable by IE, FF, and Chrome today. Most (all but IE10?) clients aren’t ready for this technique yet.

  3. Chris says:

    @John – I think you’re missing the point. As Stephen said: “The CSS Grid Layout standard is only supported by Internet Explorer 10 … it is only practical to take advantage of CSS Grid Layout when building Metro style applications with JavaScript. ”

    The point of this article is to look ahead and get your hands dirty with a new (and badly needed) way to create page layouts. I think the IE team has done great here, and I really hope the other browser vendors make plans to add support.

  4. Peter says:

    Well here we have some css that i would love to use, the current css/div usage to emulate a table are just horrible…

  5. I find some incredible irony, it takes Microsoft who for years has graded down the internet as a whole with IE6 and IE7 to solve the insanity of CSS grid systems… with a custom ms grid system.

    I sure hope this gets adopted into major browsers ASAP, the current positioning nonsense is ridiculous.