Laying out HTML with CSS Grids

I’ve been working quite a lot lately with HTML and CSS and one of the things that I’m more than prepared to admit that I’m rubbish at is CSS-based layout.

For those without a black-belt, CSS layout feels like a set of incantations that you have to get in exactly the right order for your content to appear even vaguely near where you hoped it might.

For me, coming from a background of XAML based layouts, I’ve found this to be a challenge until I started to make use of the CSS grid layout. It’s worth saying up-front that this is available in IE 10 (see “can I use?”) which suits my current purpose but support isn’t widely available in other browsers.

For the full definition of CSS grid there’s the W3C document and there’s also a very decent guide to it as a developer feature of IE 10 – because of the current standards status the grid bits are all vendor prefixed -ms- in IE 10 right now.

I think if you’re used to XAML based grids then you’re going to feel right at home.

Choosing Grid

To set up some element to use Grid style layout you set the display style attribute to a value of -ms-grid;

<!DOCTYPE html>
<html>
<head>
  <style>
    body
    {
      height: 100%;
      margin: 0;
      background-color: #ff6a00;
      display: -ms-grid;
      overflow: hidden;
    }
  </style>
  <title>My Grid Page</title>
</head>
<body>
</body>
</html>

that gives me a big orange page that occupies 100% of the browser height (and width) without any scrollbar.

The body element is now acting in "grid" mode.

Setting Up Rows/Columns

This is very much like XAML in that we define a set of rows/columns and we define the dimensions for them as either;

  • auto – i.e. size to the content in the row/column (this is auto in XAML)
  • a size unit – i.e. 96px or 2em or whatever (this is the same in XAML)
  • fr units – i.e. a fraction of the remaining vertical/horizontal space ( this is * in XAML )
  • min-content – i.e. size to the the minimum width/height of elements in the row/column
  • max-content – i.e. size to the maximum width/height of elements in the row/column

What's nice about all of this being defined in CSS is that the HTML content is left completely clean and devoid of anything related to layout. I’m not sure whether you could set the RowDefinitions and ColumnDefinitions of a XAML Grid via a style – I must admit that I don’t think I ever tried.

Adding and Positioning Content

Regardless, as an example if I have the content;

<!DOCTYPE html>
<html>
<head>
  <style>
    body
    {
      height: 100%;
      margin: 0;
      background-color: #ff6a00;
      display: -ms-grid;
      overflow: hidden;
    }
  </style>
  <title>My Grid Page</title>
</head>
<body>
  <div id="myGrid">
    <div id="oneOne">
      This is some content</div>
    <div id="twoTwo">
    </div>
    <div id="threeThree">
    </div>
    <div id="threeFour">
    </div>
    <div id="fourFour">
    </div>
  </div>
</body>
</html>

I can then leave it to styling to lay this content out into a grid via pure CSS (inlined here for simplicity);

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Grid Example</title>
    <style type="text/css">
        html
        {
            height:100%;
        }
        body
        {
            height: 100%;
            margin: 0;
        }
        #myGrid
        {
            height: 100%;
            background: orange;
            display: -ms-grid;
            -ms-grid-columns: auto 1fr 2fr 96px;
            -ms-grid-rows: auto 1fr 2fr 96px;
        }
        #oneOne
        {
            -ms-grid-row: 1;
            -ms-grid-column: 1;
            background-color:#ffd800;
            height:128px;
        }
         #twoTwo
        {
            -ms-grid-row: 2;
            -ms-grid-column: 2;
            background-color:#f00;
        }
        #threeThree
        {
            -ms-grid-row: 3;
            -ms-grid-column: 3;
            background-color:#0094ff;
        }
        #fourFour
        {
            -ms-grid-row: 4;
            -ms-grid-column: 4;
            background-color:#000;
        }
    </style>
</head>
<body>
    <div id="myGrid">
        <div id="oneOne">This is some content</div>
        <div id="twoTwo"></div>
        <div id="threeThree"></div>
        <div id="threeFour"></div>
        <div id="fourFour"></div>
    </div>
</body>
</html>

giving me a layout of;

image

where the sizing is;

  • first row and column sized to content
  • last row and column are a fixed 96px
  • 2nd row width and height and 3rd row width and height are ratio'd 1:2

just like a XAML based grid Smile

Handling Alignment

It's also possible to decide how to align content within row/column if that content doesn't fill or overflow the row/column via;

ms-grid-row-align and -ms-grid-column-align

which can be center, end, start and stretch which nicely gets around how this works in XAML where you had different enum values for vertical/horizontal alignment.

It's possible to have an element span more than one row or column via -ms-grid-column-span and -ms-grid-row-span and you can have more than one element in a single cell although it's more sophisicated than the XAML world because there's a specific -ms-grid-layer where -ve values are stacked to the back and +ve values to the front and 0 is the default.

So, with an additional element;

<body>
    <div id="myGrid">
        <div id="oneOne">This is some content</div>
        <div id="twoTwo"></div>
        <div id="threeThree"></div>
        <div id="threeFour"></div>
        <div id="fourFour"></div>
    </div>
</body>

and tweak with a little of the styling;

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Grid Example</title>
    <style type="text/css">
        html
        {
            height:100%;
        }
        body
        {
            height: 100%;
            margin: 0;
        }
        #myGrid
        {
            height: 100%;
            background: orange;
            display: -ms-grid;
            -ms-grid-columns: auto 1fr 2fr 96px;
            -ms-grid-rows: auto 1fr 2fr 96px;
        }
        #oneOne
        {
            -ms-grid-row: 1;
            -ms-grid-column: 1;
            background-color:#ffd800;
            height:128px;
        }
         #twoTwo
        {
            -ms-grid-row: 2;
            -ms-grid-column: 2;
            background-color:#f00;
        }
        #threeThree
        {
            -ms-grid-row: 3;
            -ms-grid-column: 3;
            -ms-grid-column-span:2;
            -ms-grid-row-span:2;
            -ms-grid-layer:1;
            background-color:#0094ff;
        }
        #fourFour
        {
            -ms-grid-row: 4;
            -ms-grid-column: 4;
            -ms-grid-layer:-1;
            background-color:#000;
        }
        #threeFour
        {
            -ms-grid-layer:1;
            -ms-grid-row: 4;
            -ms-grid-column: 3;
            background-color:red;
            opacity:0.5;
            width:48px;
            height:48px;
            -ms-grid-column-align:start;
            -ms-grid-row-align:end;
        }
    </style>
</head>
<body>
    <div id="myGrid">
        <div id="oneOne">This is some content</div>
        <div id="twoTwo"></div>
        <div id="threeThree"></div>
        <div id="threeFour"></div>
        <div id="fourFour"></div>
    </div>
</body>
</html>

then we see;

image

and so the black square in row,column (4,4) has disappeared behind the blue square which is spanning [3,3],[3,4],[4,3],[4,4] and has a layer of 0 so covers the black square which is at -1.

There is a red square at 4,3 at layer +1 so it shows up but it has 50% opacity and so shows up as purple because of the red/blue mix.

Wrap Up

Generally – CSS Grid seems like a complete 100% win to me other than it’s obvious lack of availability right now. I’ve found that it makes standard layouts really easy and I’m making use of it everywhere that I can.

SteveB at the Microsoft Developer Forum, Japan

Just a link to some interesting things that SteveB talked about at the recent developer forum in Japan;

I can’t find an online video of the session yet but the transcript is up here and has some interesting pointers around a few future areas.

Please note that I’m not attempting to add commentary or interpretation here, I’m just quoting the public press release and suggesting that it’s very worth reading.

Here’s some snippets – firstly around HTML and JavaScript;

“The third area that I think will be increasingly important is HTML and JavaScript. We've made a big investment, obviously, in Windows and IE9 in our HTML and JavaScript support, but more and more of the world's programmers will be fluent in these technologies in addition to whatever skills people have in C++ and C# and a variety of other important skills. But we have to recognize that more and more of the world's talent will know these techniques. And whether it's writing a website or a client application, or a server application, we want to build and develop the range of things that you can do not only using .NET, but also in using HTML and JavaScript. And, in fact, even how you can weave these things together into sensible programs in the future.”

and then around the move to ARM;

“Just think back three or four years ago and how quickly performance and size, and miniaturization and the move to ARM processors has happened. We've announced with Windows that we're going to support system-on-a-chip "architectures, not only from Intel and AMD, but also from a set of ARM vendors.”

and around Visual Studio;

“Today you write a program and as you're writing it you have to say, what computing resources does it use, how much of it runs on a client device? How much of it runs in the server? How is my server going to get set up and provisioned? How is my application going to get deployed? How do I deploy it in a redundant fashion, to have good business continuity, in the event of the kind of natural disaster that we saw here in Japan? As we are rebuilding Visual Studio, .NET, Windows Azure, we essentially are designing around the automation of program development and deployment, and the operation of those activities.”

and then around Windows;

“We're obviously hard at work on the next version of Windows. Windows 7 PCs will sell over 350 million units this year. We've done a lot in Windows 7 to improve customer satisfaction. We have a brand new user interface. We've added touch, and ink, and speech. And yet, as we look forward to the next generation of Windows systems, which will come out next year, there's a whole lot more coming. As we progress through the year, you ought to expect to hear a lot about Windows 8. Windows 8 slates, tablets, PCs, a variety of different form factors.

The browser is an area where we've been very active. Internet Explorer 9 is the fastest browser around because of the way that we've married it to Windows systems and allow essentially full exploitation of the hardware to have the fastest and most beautiful Web on the planet run on Windows systems.

We've integrated the browser into Windows more fully, so that you can put jumplists, and pin those to the taskbar on Windows. We've improved JavaScript performance. We're running on downloads that are about five times the rate of customer acceptance that we saw on IE8. and when it comes to HTML and JavaScript, and the browser, there will be simply no one who pushes that, not Google, not Firefox, nobody will push that faster and harder than we push with IE.”

and finally around developers Smile

“The relationship with developers is the most fundamental relationship between Microsoft and its customers. You're it. You write the programs, the applications that really turn on all of our customers to the power of information technology, whether you're writing for the phone or the Xbox, the PC, or the tablet, your work is the work of our industry. And our No. 1 goal in life is to support the developers, developers, developers here in Japan and across the world.”

Very interesting stuff – I’ll link to the video as/when I find it.

IE9 and Network Capture for Diagnostics

Yesterday, I was doing a little work with Silverlight and I’ve got this little sample that I’m working on;

image

and one of the things that it does it talk XML or JSON to a back-end service depending on the value of the ComboBox up in the top right hand area.

I wanted to do a little diagnosing around this and, usually, I turn to Fiddler for this kind of diagnostic work but I’m running the IE9 RTM (download) and so I thought I’d use the network capture in there rather than rely on Fiddler. With a quick F12, I’m up and running;

image

and then I can exercise the Silverlight application a little and see the results of my HTTP GET and POST;

image

and zoom in to the detail view and see the JSON data coming back;

image

along with headers, etc…

image

and it’s all cool and quick to get going and you might even notice that it’s working for traffic to localhost which is something that I think Fiddler finds a bit tricky (although if I remember correctly, there’s workarounds here).

That said, this traffic was all carried by Silverlight’s browser HTTP stack which gets traced here by IE. If I switch to using Silverlight’s client HTTP stack then I don’t think IE (as you’d expect) has any visibility of that traffic and so it’s back to Fiddler at that point… Smile