Using CSS Grid with IE Fallback

I love using CSS Grid in my themes. It lets you:

  • Quickly build advanced layouts with minimal (and readable) CSS
  • Build flexible columns with fixed width gutters, without all the nested divs other approaches like Bootstrap employ
  • Easily center elements horizontally and vertically

And much more. It currently has 84% support globally, but to provide support for old versions of IE you’ll need fallback CSS.

CSS Example

In my starter themes I use a fixed sidebar width (355px) and flexible content area. Using CSS Grid:

.content-sidebar .content-area {
display: grid;
grid-template-columns: 1fr 335px;
grid-column-gap: 32px;
}
.sidebar-content .content-area {
grid-template-columns: 335px 1fr;
}
view raw style.css hosted with ❤ by GitHub

To add IE support we’ll first use traditional floats, then wrap all our grid-related styling (including the styles to “undo” the floats) in @supports( display: grid ). This is like a media query but it works based on browser support.  I’m using simple percentage widths for the IE floats – it won’t perfectly match the grid styling but it will be close enough, and better than two full width columns.

.sidebar-content .site-main,
.content-sidebar .site-main {
float: left;
width: 65.75%;
}
.sidebar-content .sidebar-primary,
.content-sidebar .sidebar-primary {
float: left;
width: 28.68%;
}
.sidebar-content .site-main,
.content-sidebar .sidebar-primary {
float: right;
}
@supports( display: grid ) {
.sidebar-content .site-main,
.content-sidebar .site-main,
.sidebar-content .sidebar-primary,
.content-sidebar .sidebar-primary {
float: none;
width: 100%;
}
.content-sidebar .content-area {
display: grid;
grid-template-columns: 1fr 335px;
grid-column-gap: 32px;
}
.sidebar-content .content-area {
grid-template-columns: 335px 1fr;
}
}
view raw style.css hosted with ❤ by GitHub

SASS mixin

I found myself repeating the same basic formula to build columns of posts so I wrote a mixin to simplify things.

/**
* Columns
*
*/
@mixin columns( $columns, $wrapper_width: null, $grid_item_element: article ) {
@if( $wrapper_width == null ) {
$wrapper_width: $grid-max-width;
}
#{$grid_item_element} {
float: left;
margin-left: $grid-gutter / $wrapper_width * 100%;
width: ( ( $wrapper_width - $grid-gutter * ( $columns - 1 ) ) / $columns ) / $wrapper_width * 100%;
&:nth-of-type(#{$columns}n+1) {
clear: both;
margin-left: 0;
}
}
@supports( display: grid ) {
display: grid;
grid-column-gap: $grid-gutter;
grid-template-columns: repeat( $columns, 1fr );
#{$grid_item_element} {
margin-left: 0;
width: 100%;
}
header, nav, aside, footer {
grid-column: 1 / -1;
}
}
}
/**
* Columns, Mobile
*
*/
@mixin columns-mobile( $columns, $wrapper_width: null, $grid_item_element: article ) {
@include media("<tablet") {
@include columns( $columns, $wrapper_width, $grid_item_element );
}
}
/**
* Columns, Tablet
*
*/
@mixin columns-tablet( $columns, $wrapper_width: null, $grid_item_element: article ) {
@include media(">=tablet", "<medium") {
@include columns( $columns, $wrapper_width, $grid_item_element );
}
}
/**
* Columns, Tablet Up
*
*/
@mixin columns-tablet-up( $columns, $wrapper_width: null, $grid_item_element: article ) {
@include media(">=tablet") {
@include columns( $columns, $wrapper_width, $grid_item_element );
}
}
/**
* Columns, Desktop
*
*/
@mixin columns-desktop( $columns, $wrapper_width: null, $grid_item_element: article ) {
@include media(">=medium") {
@include columns( $columns, $wrapper_width, $grid_item_element );
}
}
view raw _helpers.scss hosted with ❤ by GitHub

This assumes you have $grid-gutter and $grid-max-width defined (example). In its simplest form you just say how many columns you want:

@include columns( 2 );

That will make two equal width columns with a fixed gutter. In IE it will make percentage-based columns and percentage-based gutters based on the values of $grid-gutter and $grid-max-width.

You can also specify a different max-width (only used for generating percentages in IE) and a different HTML element to target (by default it uses <article>). There are additional mixins that apply the column styling to specific breakpoints.

@include columns-mobile( 2, 400px, li );
@include columns-tablet( 3, 700px, li );
@include columns-desktop( 4, 1000px, li );

Advanced Example

On a site currently under development, the homepage has a post listing area that displays four full-width posts on mobile (screenshot), three posts in columns on tablet (screenshot), and a more complicated grid on desktop:

On IE we display it as four columns (screenshot). In modern browsers its broken into 9 equal columns, with the first post taking up 4 columns and the remaining three taking up 5 columns beside it. I’m using the @include columns(); mixin for the IE-fallback, then override the grid settings with my more advanced requirements.

.module.type-large-post-listing .wrap {
@include media(">=tablet", "<medium") {
@include columns( 3 );
article:last-of-type {
display: none;
}
}
@include media(">=medium") {
@include columns( 4 );
@supports( display: grid ) {
grid-template-columns: repeat( 9, 1fr );
grid-gap: 32px;
article:first-of-type {
grid-row: 2 / 5;
grid-column: 1 / span 4;
.entry-content {
padding: 16px;
}
}
article:not(:first-of-type) {
grid-column: span 5 / -1;
display: grid;
grid-template-columns: repeat( 11, 1fr );
grid-column-gap: 16px;
.entry-header {
grid-column: 1 / span 4;
}
.entry-content {
grid-column: span 7 / -1;
align-self: center;
}
}
}
}
}
view raw _home.scss hosted with ❤ by GitHub

Your Turn

Have any CSS Grid tips or examples? Please share them in the comments below.

If you’d like to learn more about CSS Grid, I highly recommend CSS Tricks’ A Complete Guide to Grid and Wes Bos’ CSS Grid Course.

css css-grid sass

Receive New Posts by Email

Comments

  1. I recently tried to use CSS Grid for a very simple layout but my client showed me that it wasn’t working on her Mac. It turned out that she had an old copy of Safari so I reverted to Flexbox without any IE fallback. It worked out well.
    (I encouraged her to postpone upgrading so that she could be a ‘legacy’ tester for the site).

    1. That’s a great point. Before we start a project, we ask our clients for two things:

      1. Access to Google Analytics.
      2. Visit Support Ally and send it to us, so we can see exactly how the client will be viewing the site (browser, OS, screen size…)

      We use the current user information and trends to determine our design approach (mobile first vs mobile responsive) and what tools we’ll have available to use (CSS Grid, Flexbox…).

      We also want to make sure the client can see the site as intended on their browser of choice. I don’t want them to always see the “fallback” version when the majority of their traffic sees a better version of their site.

  2. Nice solution, Bill. Thanks for sharing (also for the educational sources). Using these mix-ins makes sense.

    By now, I have seen a lot of presentations and online tutorials about Grid and found the ones by Rachel Andrews and her Grid by Example also very illuminating, especially her recent talk in which she goes more into the details of how browsers determine the width and height of the grid-cells based on css and why columns of 1fr do not always end up being the same width or seem to do what you expect. I found that talk very helpful and interesting, and it also contains suggestions for fallback on older browsers. And ofcourse there are more great talks and sources.

    Next to your fallback solution I have seen solutions come by based on Flexbox and/or columns that seem to work too, although float is probably the most supported. The advantage of both of them is not to have to add extra classes to the html-markup that float-based grids often needed, especially when using frameworks. It probably depends on how far you want to go back in browser support and what deviations in ui are acceptable on a given use case.

    When I looked at the browser-usage on the websites I managed, it seems to me that I don’t need to bother too much about fallback, since smartphones mostly are on-dimensional (1 column) and desktop browsers are mostly new enough to have support. So when not working for clients as you do, I might even decide to go just grid and use 1column mobile display as fallback. It all depends on the usage case.

    It seems that the current thinking is that we can offer the best presentation when browsers support the newer css and offer a good enough presentation on older browsers. To me that seems fair enough and results in lighter css at a least. It makes it easier to use cleaner markup and code.

    1. Yes, it definitely depends upon the browsers you need to support and how important the column structure is to the site’s usability.

      I’ll often use grid-only CSS when it’s an enhancement; the site still looks and works well without it. For instance, breaking a bulleted list into two columns is a “nice to have” feature, but not having it doesn’t make the site unusable.

      Alternatively, major layout changes like having “content” and “sidebar” display next to each other are important enough to get a fallback.

      All of our mobile first sites are “sidebar-less” and have one column of content. Like you mentioned, we can use grid-only styling to enhance the desktop look, but not worry about fallbacks since the site will work well without the columns in old browsers.

  3. I’ve been doing it the other way around, instead of using grid as an enhancement, I’ve been using it as the default since it serves the majority and then adding fallbacks for the minority. This way you can use ‘@supports not ( display: grid ) {..}’ for the fallbacks then just remove that code in one go in the future when you no longer need to support them older browsers.

    1. I originally used that approach, but found that most of the browsers I wanted to target with my fallback styles do not support @supports so my fallback styles were being ignored.

      All versions of IE and old versions of Safari do not support @supports (see here). It really confused me why my fallbacks were being ignored on my old iPad. Once I flipped things, everything was better.

      Every browser that supports display: grid also supports @supports, so it’s safe to wrap your grid styles with it.

Leave a comment