CSS Grid Resources

Logo
Other CSS Grid Demos & Examples

Feature Queries for CSS Grid fallbacks

Introduction

When showcasing how CSS Grid is used for creating a new cool hero section for our homepage, we stumbled upon one block: browser support. Now don't get me wrong here, CSS Grid is very well supported. All the current versions of modern browsers, from Firefox to Microsoft Edge offer full support for this great new layout technique. Unfortunately, not everybody is using these browsers (just yet).

Based upon statistics from Browser Market Share Worldwide, an estimated (shrinking) 30% is currently browsing the web without full CSS Grid support. However, this is hardly a reason to withhold the other (growing) 70% a great CSS Grid based layout experience. The reason is...feature queries!

Feature queries can be used to test if a browser is able to understand a CSS feature. With the @supports rule the browser is asked (queried) whether or not a specific CSS property is supported. Then, if the answer is positive, the browser is instructed to apply a series of style rules.

In the example below the browser is first asked if it supports CSS Grid with @supports (display: grid). Then, if grid is supported, the browser is told to create a grid with a single column and 4 rows for elements using the .hero-grid class. If the browser does not support either grid or the @support rule, all the styling that follows will be skipped.

That last part is crucial, if the browser does not support the CSS property OR does not understand feature queries, the code included in the query will be skipped.

CSS Code
-----------

@supports (display: grid) {
  .hero-grid {
    display: grid;
    grid-template-columns: auto;
    grid-template-rows: auto repeat(2 , 80px) auto;
  }
}

The feature query test can also include a not operator. That means that the browser can be told to do something, if a specific feature is not supported. I have seen quite a few examples where this approach is used to provide alternative layout code, like flexbox, for browsers that do not support CSS Grid. I am showing an example below that I actually have seen in the wild — just be aware that this does not work!

Why? Well, if feature queries are not supported, the browser won't get to the code inside. For example, as soon as IE11 gets to that support query in the code block below, it skips over everything inside, and continues as of the closing bracket. And although it does support flexbox, the line with display: flex is never read and therefore not rendered as such. With that being clear, let's look at a proper way to create a fallback layout for browsers that are not supporting CSS Grid.

CSS Code that does not work !!
-----------

/* flexbox fallback if the browser does not support display:grid */
@supports not (display: grid) {
  .hero-grid {
    display: flex;
  }
}

Fallback first

The CSS Code in the first code box above comes from a showcase where I used CSS Grid to create a new hero section for our homepage. If you hop over to that demo real quick you will see that is looks great, on small mobile screens and larger (desktop) screens. Unless you are using IE11, then it looks that what you see in the image below.

Terrible? At the very minimum the content is accessible. IE11 renders all of that, but skips the CSS such as display: grid that it does not support. Where no (layout) code is provided, it simply renders the browser's default styles and stacks all elements.  Using a 'fallback first' approach, the experience for IE11 visitors can be made significantly better.

CSS Grid Editor screenshot | Mobile grid

In short this approach means first defining the fallback layout with code these browsers understand. Then, after that experience is 'good enough' a better layout experience can be created with CSS Grid code inside of a feature query.

The CSS code box below represents a simple flexbox setup, creating the initial layout for our hero section. (I replicated the HTML code from my 'A new homepage for CoffeeCup with CSS Grid' article so you don't have to keep jumping back and forth).

If no 'grid code' is added, this code determines what our layout will look like in all browsers (that support flexbox). Once additional grid code is added, this code is still what determines the layout in IE11 and all other browsers that do not support grid. I placed a screenshot of how this looks in IE11 below the HTML code box.

Not as grand as our animated CSS Grid layout, but very workable indeed.

CSS Code
-----------

/*fallback first (keep it simple!)*/

.hero-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-end;
  max-width: 1600px;
  margin: 0px auto;
}

.hero-text-wrapper {
  flex: 100%;
  padding: 40px 0 20px 0;
}

.hero-image {
  max-width: 40%;
  margin: 0px 0.2%;
}

.layer-3 {
  max-width: 28%;
}

.layer-2 {
  max-width: 28%;
  order: 3;
}
HTML Code
-----------

<section class="hero-section">
  <div class="hero-grid">
    <div class="hero-text-wrapper">
      <h2 class="hero-text creative">create</h2>
      <h2 class="">lorum</h2>
      <h2 class="">ipsum</h2>
    </div>
    <picture class="hero-image layer-3">..</picture>
    <picture class="hero-image layer-2">..</picture>
    <picture class="hero-image">..</picture>
</section>
CSS Grid Editor screenshot | Mobile grid

It is beyond the scope of this article to look at the code in detail, but let's quickly go over some of the highlights. 

Most importantly, the .hero-grid container is instructed to be a flex parent with display: flex. This automatically makes all content inside flex children, who are allowed to go to a next line, to wrap, when needed.

Then the text container is instructed to take up the full width of the container through flex: 100%. The 3 images will consequently move down to the next line.

The images all share the .hero-image class. The margin of 0.2% creates some space between them. With a maximum width of 40%, the last image will still wrap to the next line. That is remedied by applying a smaller width of 28% to the images with the .layer-2 and .layer-3 classes. Finally the image with the .layer-2 class is moved to the right using the flexbox order property.

A decent layout overall, now let's spiff it up with CSS Grid!

Jumping forward (into the grid)

This is where we are going to use the feature query to supply modern browsers with some fancy grid code. The code is the same as previously used — basically all we need to do is wrap it in a support query.

First we are going to tackle the mobile view. We start with our test, if the browser supports display: grid, create a single column and 4 grid rows. Support for 'grid' on mobile browsers is (almost) universal, so people on phones and (smaller) tablets will see the grid layout defined in the code box. Except..if you look at the image below the box, you will see this doesn’t do what we want. Several fallback styles are still applied, influencing what is happening in our Grid layout.

CSS Code
-----------


/*Setting up our mobile grid*/

@supports (display: grid) {
  .hero-grid {
    display: grid;
    grid-template-columns: auto;
    grid-template-rows: auto 80px 80px auto;
  }
}
Mobile view
Fixing fallbacks

What we need to do here is review the layout styles we specified in the 'fallback' code block. For each selector we need to decide if any of the applied styles influence our desired result, and redefine the styles where needed. Doing that within the @support query makes sure these new styles will not be read by browsers that do not understand CSS Grid and therefore will not mess up our fallback layout.

Our first candidate is the .hero-grid selector. Where we previously aligned the flex items to the bottom of the container, now we want them to start at the top of each grid cell. From there they will go down, no longer overlapping the text and instead disappearing behind the image in the next row down. To do this we change the value of the  align-items property from flex-end to start

The styles for the .hero-text-wrapper are just fine, the images are not overlapping it anymore and it will sit in the very first grid row as intended.

The images are still very small due to the width constraint applied to the .hero-image selector. Setting that to 100% already gives us largely the layout we are looking for. We do want to center them though — for that we set the left and right margin to auto (from 0.2% initially).

The rest is just tweaking to get the effect we want. The images in the back need to be a little smaller to create the perspective — I set these values to 90% and 96%. Also, the flexbox order property is pushing .layer-2 image forward. We reverse that by setting the order value to 0.

To top it off I added a bit of shadow on the .hero-image selector, emphasizing the 'depth perspective' and resulting in the design showcased below the code box. Spiffy!

CSS Code
-----------

/*reversing conflicting fallback styles for browsers that understand css grid*/

@supports (display: grid) {
  .hero-grid {
    align-items: start;
    width: 98%;
  }

  .hero-image {
    max-width: 100%;
    margin: 0px auto;
  }

  .layer-3 {
    max-width: 90%;
  }

  .layer-2 {
    max-width: 96%;
    order: 0;
  }
}
Mobile view
Jumping forward (for wide screens)

Without further changes the layout will look like the above on all browsers that support CSS Grid — from mobile browsers to super large screens. We really should make good use of the real estate of wider screens and show more of the images that are currently placed in the back.

To do so we going to change our grid structure at the 64rem (1024px) breakpoint. (Clearly this could have been done at any other (custom) breakpoint as well. The plan is to continue showing the app screenshot in the front, but with the other 2 images on the side. This is similar to the fallback layout, except that the main image will partially overlap the side images.

For this we will need 4 columns and 2 rows. We prototyped the desktop layout before with the help of CSS Grid Builder, so we can simply grab that code and place it in the support query. 

The code below tests for 2 conditionals: 1. if the browser supports CSS Grid (or not), and 2. if the viewport is wider than 64rem (or not). The container was already instructed to become a grid parent for CSS Grid supporting browsers, so we don't have to worry about that — we only need to create the newly specified grid structure. As explained in detail in my previous article, this  will initially create a mess...

To summarize: the 4 elements will automatically be placed in the 4 grid cells in the first row. The second row will be collapsed since it has no height specified and no content. Since this could only be seen in the video in the other article, I added an image below the code box to illustrate this.

CSS Code-----------

/*create a new grid and place items at the bottom (end) of the rows*/

@supports (display: grid)
{
  @media screen and (min-width: 64rem) {
    .hero-grid {
      grid-template-columns: 20% repeat(2 , 1fr) 20%;
      grid-template-rows: 300px auto;
      align-items: end;
     }
  }
}
Desktop view

The solution? We will need to tell our grid kids where to go in the grid — what cells they should to use for their positioning. There are various methods, but because of the overlap the line-based placement technique suits best. The code below is explained in detail in the preceding article, but to summarize what is happening: each element is specifically instructed to position itself between horizontal and vertical grid lines.

In addition we need to tell the side images for which we constrained the width before the breakpoint, that can now take up 100% of the available. With the placement code, the new width specification, and some font style updates (which I left out of the code example), the wide screen layout and design is ready. The image below the code box illustrates this.

CSS Code-----------

@supports (display: grid)
{ 
  @media screen and (min-width: 64rem)
{
    .hero-text-wrapper {
      grid-column: 1 / 5;
      grid-row: 1 / 2;
    }

    .hero-image {
      grid-column: 2 / 4;
      grid-row: 2 / 3;
    }

    .layer-2 {
       grid-column: 3 / 5;
    }
    .layer-3 {
      grid-column: 1 / 3;
    }
}
Desktop view

Wrapping it up (and a plea for help)

The 'fallback first' method works like a charm, the (layout) design looks great, even on browsers without grid support. I created a slim codepen with the essential code (without the animation for now) that can be used to test or play with.

On the downside, this method is a lot more involved than creating a grid layout right off the bat. We can do better!

We would like to add a 'Feature Query' switch to CSS Grid Builder. This will allow for creating fallback layouts fast. Then switch to the other mode and design away for modern browsers. And...it will also work the other way around — create an awesome Grid Layout first, then define styles for non-supporting browsers.

Here's how you can help make it happen...

We made CSS Grid Builder free so more people can learn CSS Grid and prototype designs using the cool new technique. It was also an experiment to see how it would work with responsive frameworks such as Bootstrap and Foundation. Our conclusion? CSS Grid is the new layout framework — "CSS frameworks" still offer value, but not for layout.

To get to the point: adding Feature Queries will allow for creating bullet-proof production ready designs, using Bootstrap or Foundation or any other framework you want us to add. But, adding Feature Queries to CSS Grid Builder will take a significant amount of work and CoffeeCup is just a small company with limited resources (that likes to pay its team for the work they do). So...we decided to create a commercial version of this app.

You can  back Feature Queries now  for just $29. Your money will be used to fund the development of Feature Queries in the app. Upon its release you will get the update (Windows & MacOS) for free. For everyone else the price will be $129.

While we work on the Feature Queries, you will immediately get a version that allows for multi-page projects. Yup, you can start designing for the future now, and add the fallbacks upon release!

Also, we will create a few (3+) cool grid layout based themes WITH fallback and gift them to the community. What do you say? Are you in? If so, please hop over to invest in the future. Me and the rest of the CoffeeCup Crew would be totally thankful for your support.

Placeholder Picture
--Bob

(and the rest of the CC team)