CSS Grid in IE: CSS Grid and the New Autoprefixer

Avatar of Daniel Tonon
Daniel Tonon on (Updated on )

UGURUS offers elite coaching and mentorship for agency owners looking to grow. Start with the free Agency Accelerator today.

In Part 1 of this series, I debunked a few misconceptions that many people have around the Internet Explorer (IE) implementation of CSS grid. This article builds on that knowledge. It would be best to go back and read that article first if you haven’t already.

Today I’m going to be tackling the biggest misconception of all: that utilizing the IE implementation of CSS grid is extremely difficult. You can easily use CSS grid in IE right now without having to give it any sort of crappy fallback layout. It really isn’t that hard.

Article Series:

  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported!

Giving IE a crappy fallback layout is a bit of a tough sell to clients. It is especially tough if this is for an intranet where 90% of the users are using IE. If you want IE compatibility, first you need to resign to the fact that you can’t use all of the fancy bells and whistles that can be found in the modern CSS grid spec. Don’t let this get you down though, you would be amazed by how much IE11 can handle, especially if it has some help from Autoprefixer.

Before I get too far into this, you need to know that this isn’t a general “how to use CSS grid” article. This article is for those that understand CSS grid, but are either too afraid or not allowed to use it, thanks to IE.

I’ll be assuming that you already have a good understanding of how to use CSS grid in modern browsers for this article. If you aren’t sure about how to use CSS grid yet, go watch Rachel Andrew’s excellent CSS grid video tutorial series. After that, go play some levels of the browser game Grid Garden to get some hands-on CSS grid experience. Once you understand the basics of how to use CSS grid in modern browsers, come back here and learn how to use it in a way that produces identical results in IE10 and 11.

Setting up Autoprefixer

Before you do anything else, you will want to get Autoprefixer up and running. Autoprefixer is a tool used for automatically adding browser-specific CSS prefixes to your CSS so that you don’t have to. It’s a bit like Babel but for CSS. (We have a great overview by the creator of Autoprefixer here on CSS Tricks.)

If you have never used Autoprefixer (or any build tool) before, then first install Node on your computer then follow this guide on how to get a basic workflow up and running. The bit in the guide specifically about Autoprefixer is found here. (I recommend the Gulp setup over Grunt if you aren’t sure which to go with.)

If you are already using Autoprefixer in your projects, make sure to update it to the latest version using this command:

npm i autoprefixer@latest -D

Some features used in the latest version of Autoprefixer are not supported in PostCSS version 5. This means that you may also need to update your version of PostCSS to at least version 6. If using Gulp, that means updating gulp-postcss to at least v7.0.0. If using Grunt, you may need to update grunt-postcss to at least v0.9.0.

Once you have an environment up and running, you will need to set the Autoprefixer grid setting to true. Without that setting turned on, Autoprefixer will not be able to do any of the cool stuff that I’m about to show you.

Update: In version 9.3.1 you can enable CSS Grid translations by simply adding a control comment to your CSS file. Learn more about it in Part 4.

The exact method for turning the grid setting on depends a lot on how you compile your code. If you were using the guide that I linked to earlier, you would have seen this snippet of code:

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

WordPress is converting all of the “>” symbols inside code snippets to >. There doesn’t seem to be a way to stop it from doing that. Please pretend that all instances of > inside code sippets are actually the “>” symbol.

Add grid: 'autoplace' to the options to turn grid prefixing on:

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ grid: 'autoplace', browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

Update: In version 9.4.0 limited autoplacement support was introduced to Autoprefixer. For backwards compatibility reasons, the new recommended setting for enabling grid translations is now grid: 'autoplace'. I have updated all the code snippets to reflect this new recommendation.

By the way, the browser settings in the tutorial are pretty outdated and will be outputting far more prefixes than you actually need. Just going with “>1%” will mean that when a browser dies, Autoprefixer will automatically stop writing prefixes for that browser. It bases browser usage on global browser data retrieved from caniuse.com.

So, these are the Autoprefixer settings that you should end up using:

var processorsArray = [
  require('autoprefixer')({ grid: 'autoplace', browsers: ['> 1%'] })
];

Now onto the fun stuff! 😃

Autoprefixer has new super powers!

You may have read Rachel Andrew’s article “Should I try to use the IE implementation of CSS Grid Layout?” That article is all about CSS grid and understanding it’s support in IE10 and 11. It’s a great article and very useful for understanding IE’s limitations. Definitely still worth a read if you haven’t already checked it out. Note that it is extremely outdated in terms of its information on Autoprefixer though.

Autoprefixer has come a long way since Rachel wrote her IE11 CSS grid article and Autoprefixer now supports far more CSS grid translations. Take a look at this new, updated version of Rachel’s table based on Autoprefixer version 8.6.4. Note that items in bold represent a change in Autoprefixer support compared to Rachel’s article:

CSS Grid Property IE10 Implementation Autoprefixer? Notes
grid-template-columns -ms-grid-columns Yes
grid-template-rows -ms-grid-rows Yes
grid-template-areas NA Yes Autoprefixer uses this to understand what the grid looks like but does not add any extra properties.
grid-template NA Yes Shorthand for grid-template-columns, grid-template-rows, and grid-template-areas
grid-auto-columns NA No IE doesn’t support auto-placement
grid-auto-rows NA No IE doesn’t support auto-placement
grid-auto-flow NA No IE doesn’t support auto-placement
grid NA No See this GitHub issue as to why this isn’t supported
grid-row-start -ms-grid-row Yes1 Span syntax requires grid-row-end to be defined
grid-column-start -ms-grid-column Yes1 Span syntax requires grid-column-end to be defined
grid-row-end NA Yes1 grid-row-start must be defined
grid-column-end NA Yes1 grid-column-start must be defined
grid-row NA Yes1
grid-column NA Yes1
grid-area NA Yes2 Autoprefixer translates the grid area into column/row coordinates
grid-row-gap NA Yes3 Generates extra rows/columns in IE.
grid-column-gap NA Yes3 Generates extra rows/columns in IE.
grid-gap NA Yes3 Generates extra rows/columns in IE.
NA -ms-grid-column-span Yes Translated from grid-column-end and grid-area.
NA -ms-grid-row-span Yes Translated from grid-row-end and grid-area.
align-self -ms-grid-row-align Yes
justify-self -ms-grid-column-align Yes

Table disclaimers

I will cover these in far more detail later in the article:

  1. Autoprefixer cannot prefix negative integers.
  2. Each grid element must have unique area names.
  3. Autoprefixer only prefixes grid-gap if both grid-template-areas and grid-template-columns have been defined. It also cannot inherit grid-gap through media queries.

grid-template-areas is your new best friend

As you can see from the updated (and much more positive-looking) table, there are a lot of cool new features in Autoprefixer now. The most important of which is its support for grid-template-areas (and by extension grid-template). By supporting grid-template-areas, Autoprefixer now understands exactly what your grid looks like. This paved the way for Autoprefixer to also support (in a limited capacity) grid-gap.

Note that Autoprefixer still does not support the shortcut grid property. This was an intentional design decision that you can learn more about in this GitHub issue. The short story is that the grid property is not only a shortcut for the templating settings but also the auto-placement settings. Since IE can’t do auto-placement and the grid-template property can essentially do anything that the grid property can do (that IE can handle), it was decided that the grid property wasn’t worth supporting.

Back when Rachel wrote her article, this was the sort of grid code you would need to write in order to support IE:

/* IE-friendly source code 26 November 2016 */
/* Code needed to make Autoprefixer work properly */

.grid {
  display: grid;
  grid-template-columns: 1fr 10px 1fr;
  grid-template-rows: 100px 10px 100px;
}

.cell-A {
  grid-column: 1;
  grid-row: 1;
}

.cell-B {
  grid-column: 3;
  grid-row: 1;
}

.cell-C {
  grid-column: 1;
  grid-row: 3;
}

.cell-D {
  grid-column: 3;
  grid-row: 3;
}

Now, you can write code like this instead:

/* Today’s IE-friendly source code */
/* Autoprefixer can now make this code IE safe */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px /
    1fr  1fr;
}

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

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

Autoprefixer will take the above code and translate it into this much more IE-friendly code for you:

/* Autoprefixer’s IE-friendly translation */

.grid {
 display: -ms-grid;
 display: grid;
 grid-gap: 10px;
 -ms-grid-rows: 100px 10px 100px;
 -ms-grid-columns: 1fr 10px 1fr;
 grid-template:
   "a   b" 100px
   "c   d" 100px /
   1fr  1fr;
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

Best of all, you can then simply change the grid-template or grid-template-areas property with a media query and Autoprefixer will automatically update all of the grid cell coordinates for you:

/* Changing a grid-template with a media-query */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px){
  .grid {
    /* Duplicating the grid-gap is no longer necessary as of Autoprefixer v9.1.1 */
    grid-gap: 10px;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

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

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

.cell-E {
  grid-area: e;
}

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

The above gets translated into this IE-friendly code:

/* Autoprefixer’s IE-friendly media query translation */

.grid {
  display: -ms-grid;
  display: grid;
  grid-gap: 10px;
  -ms-grid-rows: 100px 10px 100px 10px 100px;
  -ms-grid-columns: 1fr 10px 1fr;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px) {
  .grid {
    /* Duplicating the grid-gap is no longer necessary as of Autoprefixer v9.1.1 */
    grid-gap: 10px;
    -ms-grid-rows: 100px 10px 100px;
    -ms-grid-columns: 1fr 10px 1fr 10px 1fr;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

.cell-E {
  -ms-grid-row: 5;
  -ms-grid-column: 1;
  grid-area: e;
}

.cell-F {
  -ms-grid-row: 5;
  -ms-grid-column: 3;
  grid-area: f;
}

@media (min-width: 600px) {
  .cell-A {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
  }
  
  .cell-B {
    -ms-grid-row: 1;
    -ms-grid-column: 3;
  }
  
  .cell-C {
    -ms-grid-row: 1;
    -ms-grid-column: 5;
  }
  
  .cell-D {
    -ms-grid-row: 3;
    -ms-grid-column: 1;
  }
  
  .cell-E {
    -ms-grid-row: 3;
    -ms-grid-column: 3;
  }
  
  .cell-F {
    -ms-grid-row: 3;
    -ms-grid-column: 5;
  }
}

The duplicate media query might look a bit ugly but I assure you that this is the best possible way that Autoprefixer can handle the media query translation. The new IE grid cell coordinates could not be placed into the same media query as the grid template definition. Doing so would lead to one of two possible outcomes.

One outcome is that the default grid cell positions would override the altered positions stated in the media query. This would cause the media query to have no effect in IE.

The other outcome would be for Autoprefixer to shift all of the styles inside the media query (yes, that includes all of the styles that you wrote yourself) to another location in the style sheet, potentially causing horrific CSS specificity issues. You can learn more about the thinking behind this decision in the now closed GitHub issue for it.

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!

Update: Though IE still doesn’t support autoplacement, in version 9.4.0, limited autoplacement support was introduced to Autoprefixer. When reading this section, keep in mind that it was written at a time when absolutely no autoplacement support was available.

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.

Autoprefixer control comments

Despite Autoprefixer’s best efforts, there are still some rare occasions when it seems like Autoprefixer is hindering you more than it is helping you. If you ever find yourself in a situation where it would be easier to not have Autoprefixer translating your code, you can turn Autoprefixer off using something called a “control comment.”

Update: As of Autoprefixer 9.3.1, it is now recommended that you use the new Grid control comments to enable and disable CSS Grid translations. Learn more about these control comments in Part 4.

autoprefixer: off

This control comment will turn off Autoprefixer translations for the entire CSS block. It will not prefix any styles before or after the point where the comment is made.

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: -ms-grid;
  display: grid;
}

autoprefixer: ignore next

If you are after more of a scalpel than a sledge hammer, the /* autoprefixer: ignore next */ control comment is more for you. “Ignore next” will skip the next CSS declaration rather than ignoring the entire CSS block.

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: -ms-grid;
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

Pre-processor comments

If you are using Sass (or another CSS pre-processor) in your project, do not use the double slash (//) method for writing these comments. Sass will strip those comments out before Autoprefixer has a chance to translate the code.

/* Input SCSS */

.normal-behavior {
  display: grid;
}

.failed-off-behavior {
  // autoprefixer: off
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
}

.failed-off-behavior {
  display: -ms-grid;
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}

Let’s recap!

So, after all that, here is the list of all the things you need to remember to be an IE11 CSS grid master:

  • Use the latest version of Autoprefixer (npm i autoprefixer@latest -D).
  • Turn on the Autoprefixer grid setting.
  • Do not attempt to use auto-placement, every cell must be placed manually.
  • Use grid-template-areas as your primary method for placing grid cells into position.
  • Use grid-template (not grid) as a shortcut.
  • Don’t use duplicate area names unless they are inside a media query targeting the same element. (not an issue in 9.3.1)
  • You can use grid-gap as long as you define both grid-template-areas and grid-template-columns.
  • When spanning multiple columns and rows, avoid counting backwards from the end of the grid. Autoprefixer doesn’t understand your grids well enough to supports this.
  • Avoid using line names for now. Give this GitHub issue a thumbs up if you want to start using them.
  • Use control comments /* autoprefixer: off */ and /* autoprefixer: ignore next */ to prevent Autoprefixer from translating certain parts of your style-sheet that are causing problems.
  • Don’t forget to test!

…and from Part 1:

  • IE does have an implicit grid.
  • IE supports repeat functionality.
  • minmax(), min-content and max-content are all natively supported.
  • fit-content() isn’t natively supported but you can work around this with auto and max-width settings.
  • IE auto is not equal to auto in modern browsers.

If you have any questions, or if this really helped you out, let me know in the comments! I’m also @Daniel_Tonon on Twitter. 😁

Up next…

In Part 3, I will be covering how to make a fully responsive flexbox-based grid in IE11. This flexbox technique even replicates grid-gap functionality!

Article Series:

  1. Debunking common IE Grid misconceptions
  2. CSS Grid and the new Autoprefixer (This Post)
  3. Faking an auto-placement grid with gaps
  4. Duplicate area names now supported!