Grid – Can I use?

Grid garden (learn grid)

Grid in IE10/11
Shows which parts of Grid you can use or not with IE10/11 when using the autoprefixer. Quite a lot

Enable in Sage:

Note CSS Grid is not used in Bootstrap. So you probably want to do this only if you are not planning to use the BS4 grid solution.

Try this in postcss.config.js. Change:

autoprefixer: true,

To:

autoprefixer: { grid: true },

But make sure you’re familiar how it works with IE11–it’s not necessarily going to be a plug and play solution. Start here 13 and here 6.

Autoprefixer still can’t save you from everything

Even Superman can’t always save everyone and Autoprefixer is no different. While Autoprefixer is able to cut down on a lot of the workload involved in making our grids IE-compatible, it can’t fix everything. It can only translate things that IE can understand. These are the many critical things that you need to be aware of if you don’t want to open the site up in IE one day and have it blow up in your face.

#Grid Gap has limited support

As you may have seen in that last example, grid-gap isn’t currently able to be inherited through media queries. If you want to use grid-gap, you will need to duplicate the grid-gap setting across all of the media queries where you define a grid template for that grid.

Update: The grid-gap media query inheritance bug was fixed in Autoprefixer version 9.1.1. It is now safe to use grid-gap in your default grid template and then let the gap setting trickle down into all of your media query grid templates.

That isn’t the only problem around using grid-gap though. It is only supported by Autoprefixer when both grid-template-areas and grid-template-columns have been defined.

Autoprefixer adds grid-gap support by using grid-template-areas to understand what your grid looks like. It then takes your grid-template-columns and grid-template-rows definitions and injects the grid-gap value between each row and column, creating extra rows and columns in IE.

If you try to use grid-gap on its own without grid-template-areas, Autoprefixer has no way of knowing what cell belongs to what grid. Without that critical knowledge, it cannot safely inject the extra columns and rows that IE needs.

That explains grid-template-areas but why do we also need to define grid-template-columns? Shouldn’t something like this be just as easy for Autoprefixer to translate?

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-areas:
    "a  b  c"
    "d  e  f";
}

.cell-a {
  grid-area: a;
}

.cell-f {
  grid-area: f;
}

Rows and columns in CSS grid default to a value of auto so can’t Autoprefixer just add something like -ms-grid-columns: auto 20px auto 20px auto;? It does that for rows, so why can’t it do the same thing for columns?

Well my inquisitive friend, I explained in Part 1 that auto in IE acts a bit differently to auto in modern browsers. When columns are set to auto in IE, they will always shrink down to the value of max-content. Modern grid columns, on the other hand, will expand to 1fr if there are no other fr units being used in that grid template declaration. This discrepancy can cause a massive difference in appearance between the modern and the IE version of a grid. The Autoprefixer team felt that it was too dangerous to make assumptions about this, so they made grid-template-columns a mandatory setting in order for grid-gap to take effect.

So that explains why Autoprefixer doesn’t support grid-gap when grid-template-columns is missing. If auto behaves so differently in IE, then why does Autoprefixer support grid-gap without the user explicitly having to define grid-template-rows? Isn’t that just as bad?

Not really. When you set display: grid; on something, it’s width will grow to the full width of its container. Its height, on the other hand, typically shrinks to the height of its content. Of course this isn’t always the case. There are a number of reasons why a grid might be taller than its content. If the grid is also a flex item and the flex container is taller than the grid, then that would be one reason why the grid might be taller than its content. In general though, if there are no other forces involved, then a grid container will always be the same height as its content.

Since the height of a typical grid is the same height as its content, in most cases, auto in both IE and modern browsers will behave identically to one another. It will only differ in functionality if the height of the grid exceeds the height of the content inside of it. For the best balance between user convenience and browser consistency, the Autoprefixer team made a choice. They decided that supporting a missing grid-template-rows property but not a missing grid-template-columns property was the best way to handle grid-gap support.

#No auto-placement! No auto-placement! No auto-placement!

I really can’t say this enough. The most important thing to remember when using CSS grid in IE is that everything must be placed manually. The instant you start thinking about using auto-placement is the instant your site blows up in IE. I have a method for dealing with grids that have an unknown number of cells in them. I’m covering that in Part 3 of this series. The main thing to know right now is that if you want to use CSS grid in an IE-friendly way, you should only ever use it if there are a known number of cells for a known number of rows and columns.

It’s this lack of auto-placement in IE that makes having access to grid areas through Autoprefixer such a blessing. Instead of having to calculate all of the coordinates manually, you can instead name each cell and then let Autoprefixer do the math for you. When using media queries, you only need to redefine the grid template and autoprefixer will recalculate all of the coordinates for you. You rarely have to do any column or row counting. It’s great!

#Area names must be unique

Update: This section is now out of date. Autoprefixer 9.3.1 supports duplicate area names. Read more about it in Part 4 of this series.

The ability to use grid-template-areas is one of Autoprefixer’s greatest strengths, though it has its limits. Autoprefixer does not have any access to the DOM. Due to this, Autoprefixer is entirely dependent on using the area name for understanding where each cell needs to be placed in the grid. This can cause clashes if you use the same area name twice in the same stylesheet.

Here is a small example. Early in the stylesheet, Grid Alpha has grid-template-areas: "delta echo". Later in the stylesheet, Grid Beta has grid-template-areas: "echo delta". We say that our grid cell belongs to area echo… so does it go in column 1 or 2?

.grid-alpha {
  grid-template-areas: "delta  echo";
}

.grid-beta {
  grid-template-areas: "echo  delta";
}

.grid-cell {
  /* What column does .grid-cell go in? */
  -ms-grid-column: ???;
  grid-area: echo;
}

Modern browsers know exactly what column to place the grid cell in because they have access to the DOM. If the cell is placed inside Grid Alpha, it will go in the first column. If it is placed in Grid Beta it will go in the second column. Autoprefixer can only read your CSS. It has no idea if the grid cell is placed in Grid Alpha or Grid Beta. All it knows is that the grid cell needs to be placed in the “echo” area. Autoprefixer resolves this conundrum by going with whichever one came last in the stylesheet. In this case, Autoprefixer will honor Grid Beta’s "echo delta" areas definition since it occurs last. If you placed the grid cell inside Grid Alpha, it would look great in modern browsers but it would be placed in the wrong column in IE.

This also means that you can’t really use the strategy of giving a component a single designated area name that is repeatedly referenced. Referencing that area name in more than one grid-template-areas property will break IE for sure. Every single area name across every single grid in your style sheet needs to be unique or Autoprefixer will freak the heck out.

The easiest way to ensure that each area name is unique is adopting a BEM style approach to naming the areas.

.grid-alpha {
  grid-template-areas: "grid-alpha__delta  grid-alpha__echo";
}

.grid-beta {
  grid-template-areas: "grid-beta__echo  grid-beta__delta";
}

.grid-cell {
  /* No more conflict :) */
  -ms-grid-column: 2;
  grid-area: grid-alpha__echo;
}

This can be pretty verbose if there are lots of columns and rows. You might want to shorten it down to an abbreviation instead. Of course, the less verbose your area names, the more chance there is of a conflict.

.grid-alpha {
  grid-template-areas: "ga_delta  ga_echo";
}

.grid-beta {
  grid-template-areas: "gb_echo  gb_delta";
}

.grid-cell {
  -ms-grid-column: 2;
  arid-area: ga_echo;
}

There is one major exception. Grid areas in media queries are allowed to be duplicates of other areas as long as the area names defined in the media query are targeted at the same element. Without this exception, it would be impossible to change the grid areas based on screen size. The main thing to remember is that each grid has to have its own set of unique area names that must not be shared with any other grids.

@media (min-width: 600px) {
  .grid-one {
    grid-template-areas:
      "alpha bravo"
      "alpha charlie";
   }
}

@media (min-width: 900px) {
  .grid-one {
    /* This is fine */
    /* It is targeting the same element */
    grid-template-areas:
      "alpha bravo charlie";
  }
}

@media (min-width: 900px) {
  /* NOT FINE! */
  /* The "alpha" area is being reused on a different element! */
  .grid-two {
    grid-template-areas:
      "alpha delta";
  }
}

#Autoprefixer has limited column and row spanning support

There are only two properties in IE’s implementation of CSS grid that will help you span multiple columns. The main one being -ms-grid-column/row-span which tells IE how many columns/rows to span. The other being -ms-grid-column/row which tells IE where to start counting from.

.grid-cell {
  -ms-grid-column-span: 2; /* number of cells to span */
  -ms-grid-column: 1; /* starting cell */
}

In modern browsers, you have access to far more options.

Autoprefixer friendly

Out of the modern ways to span multiple cells, Autoprefixer fully supports the following. Feel free to use any of these methods as much as you like:

Specify a starting line and the number of lines to span (similar to IE):

.grid-cell {
  grid-column: 1 / span 2;
}

Specify an end line, then span backwards:

.grid-cell {
  grid-column: span 2 / 3;
}

Specify a starting line and an end line directly:

.grid-cell {
  grid-column: 1 / 3;
}

Specify only a number of cells to span using grid-column/row-end. Remember that IE can’t do auto-placement though. A starting line will still need to be specified elsewhere in the style sheet:

.grid-cell {
  /* Make sure you specify a starting line elsewhere */
  grid-column-end: span 2;
}

Specify only a starting line:

.grid-cell {
  /* The short way */
  grid-column: 1;

  /* The more verbose way */
  grid-column-start: 1;
}
Autoprefixer unfriendly. Here be dragons!

Now this is where Autoprefixer reaches its limit. The following methods are supported in modern browsers but are not supported by Autoprefixer. This is mainly due to Autoprefixer having no idea what grid the grid cell belongs to since it can only base its decisions on what is in the stylesheet.

Specify a starting line and how many lines from the end of the explicit grid to span:

.grid-cell {
  grid-column: 1 / -1;
}

Specify both the start and end line from the end of the explicit grid:

.grid-cell {
  grid-column: -3 / -1;
}

Specify only how many lines to span using the shorthand syntax (issue in GitHub):

.grid-cell {
  /* Update: This is now supported as of Autoprefixer version 9.1.1 */
  grid-column: span 2;
}

Specify only a backwards span (IE can’t span backwards):

.grid-cell {
  grid-column-start: span 2;
}

Specify only an end line (IE doesn’t understand end and Autoprefixer doesn’t know where the start is):

.grid-cell {
  grid-column-end: 3;
}

So, basically avoid counting backwards from the end of the grid and you’ll be fine. 😊

#Avoid using line names for now

One of the cool features of modern grids is giving grid templates line names. Instead of using numbers to reference a line, you can give the line a name and reference that instead. Since Autoprefixer supports grid areas, you would think that they would also support line names. Unfortunately, that isn’t the case. As of version 8.6.4, Autoprefixer does not support line names (at the time of writing). Don’t worry though! It’s not that it is impossible to support (at least not entirely), it just hasn’t been a high priority for them. If you love using line names in your grids then let them know about it in the GitHub issue for it. Post your use cases and it will surely increase the priority of the feature. In the meantime, see if you can use grid areas instead for now.

Keep in mind that, if it is going to be implemented, then every line name across your stylesheet would need to be unique. Like with grid areas, Autoprefixer wouldn’t know what line name belongs to what grid. The only way it can tell is if every line name in the stylesheet is unique (excluding media queries).

Update: Since duplicate area names are now supported, there is no reason why duplicate line names couldn’t be supported as well.

#You still need to test!

IE will behave itself most of the time as long as you follow all of the rules we’ve covered so far. That said, IE can still be a bit unpredictable. Just recently, I made a grid item a vertical flowing flex container and encountered an odd bug in IE11. The column width was set to minmax(min-content, 350px) but IE seemed to treat min-content like max-content in this circumstance. This completely broke the layout. Changing it to minmax(0, 350px) fixed the issue. Just goes to show that IE’s grid implementation isn’t quite perfect.

There are also times when you might accidentally forget to explicitly place grid cells. We build our grids in modern browsers because they have the nice grid development tools (especially Firefox). Modern browsers have auto-placement, though. This means that you might be halfway through building your grid then get called away for a moment. When you return to your desk, you see the layout looking beautiful in your browser, but you completely forget that you haven’t explicitly placed any grid cells yet. You move onto the next thing, blissfully unaware that you have left IE in a completely broken state.

Neither of those issues will reveal themselves until you test your site in IE11. Any time that you get a grid looking good in a modern browser, open it up in IE and double-check that it still looks the way you expect it to.