Soon, Internet Explorer 11 will be released. Yet IE8 is used by 4.5% of our users, and we want to serve them with a great reading experience on our new responsive website.

Responsive Web Design (RWD) can be implemented in many fashions. In our case, we chose the mobile-first way, which means that we enhance the experience depending on your device, on top of the lowest common denominator: a simple mobile phone (dare I say: a feature phone).

As Brad Frost wrote in his article about mobile-first responsive web design:

Mobile-First Responsive Web Design is a combination of philosophies/strategies, and ultimately boils down to a broader application of good ol'™ web best practices.

But when supporting older, buggy and incapable browsers, we have to wave some of the "good ol' web best practices" goodbye... so, how do we make sure we don't cripple our codebase with hacks for Internet Explorer so the other 95.5% of our readers still benefit from the best experience possible?

The IE8 bottleneck

Supporting IE8 on our responsive platform means we cannot develop using these technologies natively:

rem

@media queries

rgba(), hsla()

:last-child, :nth-child(), :first-of-type, â€¦

:empty

:not()

calc()

.ttf, .otf, .woff fonts

multiple backgrounds

background-size

vw, vh, vmin, vmax

:checked, :valid, :invalid, :required

box-shadow

transforms (rotate, translate, skew, scale, matrix)

border-radius

opacity

getElementsByClassName

getComputedStyle

addEventListener

geolocation

canvas

HTML5 video

HTML5 audio

This is a big problem because we want to build a very lightweight website which uses modern features in a performant and elegant way. In order to deliver a similar experience to IE8 and modern browsers, we would have to write parts of the application more than once. As the device landscape is growing exponentially, this can heavily impact our velocity and the amount of technical debt in an unsustainable way.

While supporting IE8, we want to alter our good coding habits as little as possible and enable IE support with the minimum required effort. In a nutshell: this means less hassle (no need to maintain two separate stylesheets), and it will be easy to remove these workarounds from the codebase.

Ultimately, we needed to start somewhere with IE8, and decided to begin with the layout, for which @media queries play a crucial part when designing for multiple device sizes. Through an advanced thought process—which in engineering technical jargon is known as "fumble and scramble with the code"—we came up with an abstraction of @media queries which enables developers to build mobile-first responsive websites that work in IE8, too.

global.css

We serve a stylesheet named global.css to everyone (except IE prior to 9, see below).

We created the mq() Sass mixin and we use it instead of raw @media queries:

// global.scss

@import "mq"; .element {

// Applies to devices at least as wide as a mobile

@include mq($from: mobile) {

color: green;

}

// Applies to devices at least as wide as a tablet

@include mq($from: tablet) {

color: blue;

}

// Applies to devices smaller than a "desktop"

@include mq($to: desktop) {

color: red;

}

}



That would be compiled into the following CSS:

// global.css

@media all and (min-width: 18.75em) {

.element {

color: green;

}

}

@media all and (min-width: 37.5em) {

.element {

color: blue;

}

}

@media all and (max-width: 56.1875em) {

.element {

color: red;

}

}



old-ie.css

To support older user agents (IE8, I'm looking at you), we can set $mq-responsive to false:

// old-ie.scss

$mq-responsive: false;

@import "mq"; .element {

@include mq($from: mobile) {

color: green;

}

@include mq($from: tablet) {

color: blue;

}

@include mq($to: desktop) {

color: red;

}

}



And it will compile into this CSS:

// old-ie.css - served only to IE <= 8

.element {

color: green;

color: blue;

}



You can see that the @media query has been rasterized, enabling support for IE8 and potentially other old browsers that do not understand it. In reality, only the styling contained in min-width @media queries will be served to old IEs (in a rasterized way). All other queries are omitted.

We serve old-ie.css to Internet Explorer prior to version 9 and global.css to the other user agents using conditional comments:

<!--[if (gt IE 8) | (IEMobile)]><!-->

<link href="global.css" rel="stylesheet" />

<!--<![endif]-->

<!--[if (lt IE 9) & (!IEMobile)]>

<link href="old-ie.css" rel="stylesheet" />

<![endif]-->



This way, old IEs will load the desktop experience out of the box.

This approach combines multiple upsides:

Mobile users don't download the code designed for older browsers

Internet Explorer downloads a bit more code than what it actually uses, but we are ok with this

When it's time to drop support for IE8, we can easily remove the bits that are dedicated to it

Play & contribute

Want to play with Sass MQ? Try Sass MQ online.

Feel free to use it in your projects, and please let us know if you think there are improvements or additional features this tool should include: contribute on Github.