Semi-auto placement of CSS Grid items in Internet Explorer (11)

2019. Mar. 22. · 2 min read
The thing: as a web developer you want to use a certain technology but you have to support IE — which has never heard about that fancy solution…

To give you an example: modern browsers can place items below each other in the same CSS Grid column creating implicit grid rows. Although IE supports (the early version of) CSS Grid, it can’t do that.

Fortunately, Autoprefixer can help a lot in making a CSS Grid layout work in IE. But it doesn’t do everything. For example, it can’t solve the placing problem mentioned above:

“The most important thing to remember when using CSS grid in IE is that everything must be placed manually.” There is no auto-placement!

OK. There is no auto-placement, but there can be semi-auto placement.

Placing everything manually is neither the funniest nor the most effective activity. So what can we do? Well, we may create a Sass mixin which places the grid items below each other in IE when included in a grid container ruleset.

@mixin ie-grid-rows($start: 1, $rows: 50) {
  @for $i from $start through $rows {
    > *:nth-child(#{$i}) {
      -ms-grid-row: $i;
    }
  }
}

This is a simple mechanism: the first direct child of the grid container (which can be any element type) gets the -ms-grid-row: 1 rule, the second gets -ms-grid-row: 2 rule and so on.

Note that I defined 50 as the number of rows. It seems to be sufficient if we do not know how many grid items the container will have (e.g. the items are created by editors in a CMS). And of course we can override the default when we know the number of items exactly.

What if…?

Say we have to place all but the first two grid items below each other. The first two items have to be in the first row (in separate columns). Can we still use our mixin? Yes we can, but we have to update it:

@mixin ie-grid-rows($start: 1, $rows: 50, $container: true, $shift: 0) {
  @for $i from $start through $rows {
    $row: $i - $shift;

    @if $container {
      > *:nth-child(#{$i}) {
        -ms-grid-row: $row;
      }
    }

    @else {
      &:nth-child(#{$i}) {
        -ms-grid-row: $row;
      }
    }
  }
}

It will be easier to understand the changes if we see how the updated mixin can be used:

.grid__item {
  @include ie-grid-rows($rows: 10, $container: false, $shift: 1);
  grid-column: 2;

  &:first-child {
    grid-column: 1;
    grid-row: 1 / 10;
  }
}

First: instead of the grid container ruleset we include the mixin in the ruleset of the grid items. That is why $container argument was added to the mixin. Its false value leads to the @else part of the new condition, which sets the -ms-grid-row rule on the grid item itself.

There is an another new argument $shift. It is used in the new calculation which defines the value of -ms-grid-row. This way in this case the second grid item (nth-child(2)) will be placed in the first grid row, because $row: $i - $shift; » $row: 2 - 1 » $row: 1.

However this also means that the first grid item would set to be in the 0th row what is obviously nonsense. That is why the mixin calculation is overridden and is set to be in the first row manually.

Update 26. March 2019.

I’ve just got the info that Autoprefixer now supports Grid auto-placement for IE too (in a limited way). From version 9.4 it can auto-place items of an explicit grid in IE.