CSS GRID Fallback for IE using SASS Lists

When placing items in a CSS Grid, in modern browsers we can rely on auto-placement to do most of the heavy lifting for us, however when providing support for IE10 & 11, we have to write CSS code to explicitly place all of your items in the Grid.

This is because auto-placement is not supported in IE10 & 11 and sadly, it is also one area where Autoprefixer can’t help us either 😦

Writing all of this additional code can often be a pain so I’ve created a utility using SASS Lists to help make it a little less painful.

But why can’t Autoprefixer help?

Autoprefixer in its simplest form will look at each line of CSS, check it against caniuse.com and if it is not supported by a certain browser, but a prefixed version is available, it will add a line that includes the vendor prefix. For example:

::placeholder {
  color: gray;
}

Would output the following after Autoprefixer has been run:

::-webkit-input-placeholder {
  color: gray;
}
:-ms-input-placeholder {
  color: gray;
}
::-ms-input-placeholder {
  color: gray;
}
::placeholder {
  color: gray;
}

Great right?

But back to CSS GRID…

If we wanted to have a grid of four items, two in each column and row, we can achieve that easily by defining the grid-template-columns and grid-template-rows on the container:

.grid-container {
    display: grid;
    grid-template-columns: repeat( 2, 1fr );
    grid-template-rows: repeat( 2, 1fr );
}

Thanks to CSS GRIDs auto-placement we don’t need to do anything else, each grid- item will be repeated twice across both columns and rows and will fit 1 fraction so will appear equal in height and width. YAY!

The problem with Internet Explorer

As mentioned at the beginning, Internet Explorer does not support auto-placement. To be able to use GRID, we have to explicitly position grid-items. If we don’t do that then all of the items will stack in the first cell of the grid 😦

This means thats our code goes from:

.grid-container {
    display: grid;
    grid-template-columns: repeat( 2, 1fr );
    grid-template-rows: repeat( 2, 1fr );
}

to:

.grid-container {
    display: -ms-grid;
    grid-template-columns: repeat( 2, 1fr );
    -ms-grid-columns: 1fr 1fr;
    grid-template-rows: repeat( 2, 1fr );
    -ms-grid-rows: 1fr 1fr;
}

.grid-item-1 {
    -ms-grid-column: 1;
    -ms-grid-row: 1;
}

.grid-item-2 {
    -ms-grid-column: 2;
    -ms-grid-row: 1;
}

.grid-item-3 {
    -ms-grid-column: 1;
    -ms-grid-row: 2;
}

.grid-item-4 {
    -ms-grid-column: 2;
    -ms-grid-row: 2;
}

😦

But it’s not all bad, looking at all of those -ms- vendor prefixes used, this is where Autoprefixer has stepped in and fixed it for us right? Sadly no.

Because we haven’t used grid-column and grid-row first, (why would we when we don’t need the grid items to be explicitly placed in any browsers other than IE? ) Autoprefixer can’t see that there is anything that needs to be prefixed.

So, thanks to IE there is now a lot more code for our grid which we have to add manually and it is all starting to get very messy…

SASS to the rescue!

There isn’t a lot we can do about the amount of code needed to ensure our Grid works in IE as well, but we can tidy it up using SASS Lists and a @for loop so that it looks better in our codebase like this:

$total-items: 4;
$ms-layout: 1 1,
            2 1,
            1 2,
            2 2;

@for $i from 1 through $total-items {
    $position: nth( $ms-layout, $i );

    .grid-item-#{$i} {
	-ms-grid-column: nth($position, 1);
	-ms-grid-row: nth($position, 2);
    }
}

There is quite a lot going on in this little snippet so let’s break it down a bit.

This is the number of grid-items on the grid.

$total-items: 4;

This is our SASS List, it contains four rows, each with the position of the grid-column and then grid-row.

$ms-layout: 1 1,
            2 1,
            1 2,
            2 2;

Next we start a loop using $total-items so that the loop does not execute more than four times. Loop through each row using nth to retrieve the values for each grid-item in the $ms-layout list that correlates with where in the loop we are, and create a new list called $position.

The new list contains only the two values relevant to that grid-item. For example grid-item-3 would have a sass list that looks like $position: 1 2;

@for $i from 1 through $total-items {
    $position: nth( $ms-layout, $i );

Finally, we output the column and row positions:

    .grid-item-#{$i} {
	-ms-grid-column: nth($position, 1);
	-ms-grid-row: nth($position, 2);
    }

Using nth again we get the first value of $position for the column and the second value for row. Done!

Here is a complete example using six grid-items:

I’m sure many of you are thinking “Why bother going to this extra effort?”

This technique doesn’t stop the need for all of those extra lines of code to ensure your grid works in IE, and once the SASS has been compiled it will still output all of those lines, so you could stop at writing the vendor prefixes for IE and it would be backwards compatible.

But, if you are like me and find yourself continually copying and pasting them from project to project, it does keep your SASS a little bit neater and for me that is always worth the effort πŸ™‚

Some Further Reading:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: