Taking a “mobile first” approach to web development poses some challenges if you need to provide a “desktop” experience for legacy versions of IE. Using a CSS pre-processor like Sass can help.
As of Sass 3.2, there is another way of catering for IE, described by Jake Archibald.
One aspect of a “mobile first” approach to development is that your styles are usually gradually built up from a simple base. Each new “layer” of CSS adds presentational adjustments and complexity, via CSS3 Media Queries, to react to and make use of additional viewport space. However, IE 6/7/8 do not support CSS3 Media Queries. If you want to serve IE 6/7/8 something more than just the base CSS, then you need a solution that exposes the “enhancing” CSS to those browsers.
An existing option is the use of a CSS3 Media Query polyfill, such as Respond.js. However, there are some drawbacks to this approach (see the project README), such as the introduction of a JavaScript dependency and the XHRing of your style sheets, which may introduce performance or cross-domain security issues. Furthermore, adding support for CSS3 Media Queries is probably not necessary for these legacy browsers. The main concern is exposing the “enhancing” CSS.
Another method, which Jeremy Keith has described in his post on Windows mobile media queries, is to use separate CSS files: one basic global file, and an “enhancing” file that is referenced twice in the <head>
of the document. The “enhancing” file is referenced once using a media
attribute containing a CSS3 Media Query value. This prevents it being downloaded by browsers (such as IE 6/7/8) which do not support CSS3 Media Queries. The same file is then referenced again, this time wrapped in an IE conditional comment (without the use of a CSS3 Media Query value) to hide it from modern browsers. However, this approach becomes somewhat cumbersome, and introduces multiple HTTP requests, if you have multiple breakpoints in your responsive design.
Sass 3.1 provides some features that help make this second approach more flexible. The general advantages of the Sass-based approach I’ve used are:
- You have full control over how your style sheets are broken up and reassembled.
- It removes the performance concerns of having to reference several separate style sheets for each breakpoint in the responsive design, simply to cater for IE 6/7/8.
- You can easily repeat large chunks of CSS in separate compiled files without introducing maintenance problems.
The basic idea is to produce two versions of your compiled CSS from the same core code. One version of your CSS includes CSS3 @media
queries and is downloaded by modern browsers. The other version is only downloaded by IE 6/7/8 in a desktop environment and contains no CSS3 @media
queries.
To do this, you take advantage of the fact that Sass can import and compile separate .scss
/.sass
files into a single CSS file. This allows you to keep the CSS rules used at any breakpoint completely separate from the @media
query that you might want it to be a part of.
This is not a CSS3 Media Query polyfill, so one assumption is that IE 6/7/8 users will predominantly be using mid-size screens and should receive styles appropriate to that environment. Therefore, in the example below, I am making a subjective judgement by including all the breakpoint styles up to a width of 960px
but withholding those for any breakpoints beyond that.
The ie.scss
file imports numerous other files, each containing a layer of CSS that builds upon the previous each layer of CSS. No CSS3 @media
queries are contained within the files or the ie.scss
file. It then compiles to a single CSS file that is designed to be served only to IE 6/7/8.
// ie.scss
@import "base";
@import "320-up";
@import "480-up";
@import "780-up";
@import "960-up";
The style.scss
file imports the code for each breakpoint involved in the design (including any beyond the limit imposed for legacy versions of IE) but nests them within the relevant CSS3 @media
query. The compiled version of this file is served to all browsers apart from IE 6/7/8 and IEMobile.
// style.scss
@import "base";
@media (min-width:320px) {
@import "320-up"; }
@media (min-width:480px) {
@import "480-up"; }
@media (min-width:780px) {
@import "780-up"; }
@media (min-width:960px) {
@import "960-up"; }
@media (min-width:1100px) {
@import "1100-up"; }
The resulting CSS files can then be referenced in the HTML. It is important to hide the ie.css
file from any IE-based mobile browsers. This ensures that they do not download the CSS meant for desktop versions of IE.
<!--[if (gt IE 8) | (IEMobile)]><!-->
<link rel="stylesheet" href="/css/style.css">
This Sass-enabled approach works just as well if you need to serve a basic style sheet for mobiles without CSS3 Media Query support, and prevent those devices from downloading the CSS used to adapt the layout to wider viewports. For example, you can avoid importing base.scss
into the ie.scss
and style.scss
files. It can then be referenced separately in the HTML.
<link rel="stylesheet" href="/css/base.css">
<link rel="stylesheet" href="/css/style.css" media="(min-width:320px)">
You’ll notice that I didn’t wrap the style.css
reference in a conditional comment to hide it from legacy versions of IE. It’s not necessary this time because the value of the media
attribute is not understood by legacy versions of IE, and the style sheet will not be downloaded.
In different circumstances, different combinations of style sheets and media
attribute values will be more appropriate.
Even if you want to don’t want to use any of the Sass or SCSS syntax, the pre-processor itself can help you to write your CSS in a “mobile first” manner (with multiple breakpoints), provide a “desktop” experience for IE 6/7/8, and avoid some of the performance or maintenance concerns that are sometimes present when juggling the two requirements.
I’m relatively new to using Sass, so there may be even better ways to achieve the same result or even to prevent the inclusion of IE-specific CSS unless the file is being compiled into a style sheet that only IE will download.