So, we’re redesigning our originally-designed-for-desktop web app in a mobile-first, responsive fashion. Here’s the deal, though: we have to support shared components across dozens of pages that may, at any point in the redesign process, be either stubbornly fixed at desktop sizes or designed in the desirable mobile-first fashion. And it all needs to work back to IE8 to boot.
That sounds like a recipe for CSS disaster, but we’ve got one fancy Sass mixin that takes care of 90% of all that.
The comments in the code help make sense of what’s all going on here, but read on for the details on why we did what we did.
Put your media queries where they belong using Sass.
If you’re not already using Sass (or LESS) to handle your responsive web designs (among other CSS black magic), you don’t know what you’re missing. By using the powerful
@content directive, this mixin allows your media queries to live right alongside selectors in your original stylesheet. You can basically say, “Hey, widget, look like this at mobile sizes, then look like this when the screen is bigger.” Then you move on to the next widget and do the same thing.
Have many, many breakpoints.
We also wrote the mixin to allow for a new breakpoint every 100px. It’s a device-agnostic approach that encourages the designer to make sure the page works great at any size. You could rework the mixin to accept a media query at literally any screen size (e.g.,
@include respond(324px)), but we wanted to promote a bit of consistency in how the breakpoints were used to keep things more organized in the code.
Mobile-first pages AND old desktop-only pages?
Yeah, that’s not ideal. We partially solved the problem by creating a new base template for these mobile-first pages that was free of all the constraints of the old pages, but we still needed to share a few components across both types of pages.
The first shared component we had to tackle was our site-wide main navigation bar. It was old, crusty and exactly 995 pixels wide (no more, no less). We didn’t want two different headers on responsive and non-responsive pages, so we redesigned the nav bar to work on both types of pages.
On older pages, we added a class of
desktop-only to the body. The
respond() mixin knows to apply all the styles you specify to elements inside a
desktop-only container, regardless of screen width. Essentially,
desktop-only pages get the sum of all the styles, i.e., the largest screen styles.
Mobile-first… and IE8?
Also not fun. We still support IE8, which inconveniently ignores media queries. This doesn’t jive well with a basic mobile-first principle: any styles written outside of a media query are your mobile—and therefore default—styles. With this setup, IE8 gets the small-screen styles. Sometimes that’s OK, but we wanted our IE8 users to get a desktop-optimized design.
That last part of the mixin means I can write a media query and pass in an argument of
ie to ensure the style also applies to any page with a class of
ie8 on the
<html> tag. Pair this with something like Modernizr to detect media query ability (or some other method of detecting IE8 if that’s all you care about) and you’re golden.
Go Forth and Design Responsively
With a few of the practical CSS considerations of mobile-first design out of the way, now there’s no excuse to go and build awesome stuff. Feel free to use the mixin to your liking, modify it, port it to LESS, or tell us ways to improve it in the comments.