Jeff Croft

I’m a product designer in Seattle, WA. I recently worked at Simply Measured, and previously co-founded Lendle.

Some of my past clients include Facebook, Microsoft, Yahoo, and the University of Washington.

I’ve authored two books on web and interactive design and spoken at dozens of conferences around the world.

I’m currently accepting contract work and considering full-time opportunities.

Blog entry // 03.02.2012 // 12:41 PM // 11 Comments

How I’m implementing Responsive Web Design

Responsive Web Design is hard. Really hard, actually. But I’ve recently been exploring ways to make it fit more neatly into my development workflow, and I thought it’d be worth sharing what I’ve learned. I don’t have all the answers, but I am finally to a point where Responsive feels worth the extra effort — and for me, that’s saying something.

Media queries vs. Javascript breakpoints

Although CSS media queries get all the love in design circles, I’ve been experimenting with using Javascript to manage the breakpoints in a responsive or adaptive layout, as well. There are definitely pros and cons to both approaches.

If you use Javascript, it’s trivial to set up a configuration where only the CSS which is needed for a particular viewport width is downloaded (Adapt.js does this very well). With media queries, the visitor is going to be downloading the CSS for every viewport width, even if they don’t need it. There’s trade-off here between HTTP requests (Javascript introduces more) and size of CSS files (media queries create larger ones). I haven’t really decided which end of that stick I prefer.

Another advantage I’ve observed to using Javascript is maintaining breakpoints in a single place. More and more, I’ve found that I not only need different CSS per-breakpoint, but also different Javascript. For example, maybe I have a navigation menu across the top of my page, and on smaller screens, I’ve decided to pull those options into a select menu. That select menu needs Javascript to operate properly, and I’d really prefer to not have that Javascript loading for visitors on larger screens. So, I need to set up my breakpoints not only for CSS, but for Javascript, as well. If I need the breakpoints for Javascript anyway, maybe I should just maintain them there, and let Javascript load the per-breakpoint CSS.

Finally, browser support for Javascript is greater than for media queries. But, frankly, media queries are well-supported in all the browsers I really care about, so this is a non-issue for me.

In the end, I haven’t really settled on which approach is better. I’ve been doing more work with media queries lately, though, and the reason is primarily that Sass has some really sweet tricks up its sleeve that make my life easier if I take this approach (more on this later).

Fluid, relative-width grids

I resisted fluid layouts for a long time, and I’m still not sold on them being the right answer in every case. I still think there’s something to be said for the approach in which you have several fixed-width layouts (one for each breakpoint). But, I have been trying to add fluid methodology to my toolbox, as well, and to that end, I created a grid system based on relative widths.

You can see what I came up with on GitHub (note that this is part of a larger CSS framework I’m working on, and it’s really not ready for primetime). It’s fairly simple, and quite flexible. It allows for CSS layouts that look like this (Sass code, of course):

One of the big keys to making this work so simply was embracing box-sizing: border-box;. I’ve actually gone so far as to set * { box-sizing: border-box; } in my initial CSS reset.

Sass media query bubbling

Sass has an absolutely killer feature called @media bubbling. In short, it allows you to nest your @media statements directly inside the CSS for the element that is going to change based on the result of the media query, like this:

In my mind, this makes media queries so much easier to maintain and organize. Love this feature — especially when it’s combined with…

Sass 3.2 @content directive for media query mixins

Sass 3.2 (which isn’t out yet, but you can gem install sass --pre to use the alpha version) has a super handy new feature for mixins: the @content directive. It basically allows you to pass a content block (i.e. lines of CSS) into a mixin like an argument. After seeing a similar idea in this article by Mason Wendell, I was able to use this feature to create a super-handy media query mixin that I called respond-to. It, too, is available for your perusal on GitHub. This made it really simple to apply different CSS based on anything a media query can handle (but notably, viewport width):

Obviously, you can just add more respond-to mixins for whatever breakpoints you are targeting. Super simple. Super readable. Super easy to maintain.

Conclusion

Responsive Web Design is hard. I don’t pretend to have all the answers. But, clever use of the tools available to us can make it a much easier pill to swallow. I’ve found that a combination of embracing fluid layouts, taking advantage of a few great features in Sass, and a bit of patience has finally made Responsive Web Design something other than a constant struggle.

Comments

  1. 001 // Kev Adamson // 03.02.2012 // 1:08 PM

    Good work Jeff. Really intrigued by the @media bubbling. Being a LESS man myself, I did a quick search and found: https://github.com/cloudhead/les…, which I think is the same thing.

    What would be really nice, which I’m not sure LESS/SASS have in their arsenal yet, is the ability to change CSS based on a single item’s size, rather than always the viewport. For example:

    .foo { (max-width=500px) { this; } (min-width=501px) {that; } }

    I think we could really have the power to refine with that.

  2. 002 // Jeff Croft // 03.02.2012 // 1:18 PM

    Hey Kev! It does look like that LESS feature is the same as the Sass one. That’s great. Glad to hear they’re adding it.

    Your feature request would be sweet, but I’m not sure how it could be done outside the browser. The “single item’s size” you refer to is calculated by the browser, and Sass/LESS can’t possibly know it ahead of time, I don’t think. Granted, in the case of everything being done in an absolute measurement like pixels, they might be able to work it out, but as soon as you introduce percentages and ems, I don’t think they could. But I could definitely be wrong about that. :)

  3. 003 // Kev Adamson // 03.02.2012 // 1:42 PM

    No, you’re quite right. LESS/SASS can - of course - only pimp what is already available to them in the spec. My thinking is that until it is actually part of the CSS spec itself in some form, then it can’t then be taken by LESS/SASS and improved / simplified.

    I don’t see why this feature couldn’t be a possibility, but then are we crossing over into JavaScript territory? But, then again, is that a bad thing? I’ve often thought an evolved CSS (possibly no longer called CSS) would be a good thing. We’re plugging holes with JS all the time, doesn’t that tell us we need a new some-what unified language? One where we can target any element on page regardless of it’s relationship to another (‘before’ another for example, rather then merely ‘after’ or ‘in’)?

    Anyway. Straying slightly off point. Good thinking on the above. I have a rather hefty project that is currently adaptive, and some of the ideas you’ve shared could well be the answer to making things more manageable. Ta.

  4. 004 // Gray Ghost Visuals // 03.02.2012 // 9:22 PM

    A bigger problem at the top alongside break points are the features supported by the targeted device we are chasing for in our projects.

    There are still many issues with features implemented on the Windows Phone 7.5 (Modernizr.touch == false`) along with many other Mobile Browsers on the market that don’t support device-width for detection. The max-device-width doesn’t change for some when the device is rotated. On an iPhone, for example, the device-width is 320px and the device height is 480px regardless of its rotation. Orientation tests only test the initial orientation, because it’s not bound to a rotation or re-size event. The Windows 8 tablet with IE10 (1366x768) actually supports touch events in both its tablet mode and on IE10 desktop.

    I’ve been using EnhanceJS by Filament and found that to be a really great start to the idea of conditionally loading resources. I think cramming @media queries within one style sheet for large sites is not the best approach performance wise because we’re still giving the device css/js that will not be used basically giving bloat to our style sheet. hmmm….back to view source on the Globe for more inspiration.

  5. 005 // Andy Hume // 03.04.2012 // 3:44 AM

    Really interesting stuff - thanks Jeff.

    To achieve (more or less) what Kev is talking about in his first comment, I’ve been using this small JS script. It’s still reasonably experimental, but when I was at Clearleft we used it on a number of client sites with some success.

    https://github.com/ahume/selecto…

  6. 006 // Henrik Helmers // 03.04.2012 // 8:28 AM

    We are working much the same way, there seems to be some convergence of coding practices in this field - about time! :P

    Just wanted to point out that you do not need JavaScript to load stylesheets on demand, try something like . Also note that the stylesheet will have to be quite large before 2 smaller requests is better than 1 big (especially on mobile).

  7. 007 // Henrik Helmers // 03.04.2012 // 8:30 AM

    Ahoi there, it stripped my markup. Try using a media query when specifying the stylesheet in the head, something like link rel=”stylesheet” media=”screen and (min-device-width: 768px)”

  8. 008 // jeremy west // 03.05.2012 // 7:09 AM

    Great article. We’ve been building a responsive “framework” of sorts at work, and seeing some of this has been helpful.

    Our current solution leverages require.js for loading resources on demand, and namely relying on Modernizr and the matchMedia polyfill to pick the right resources. We have yet to tackle dynamically loading CSS simply because there’s not a reliable way of knowing when its actually loaded like there is with js files, and certain application code may rely in some way on the right CSS being present.

    I’m still skeptical about the usefulness of RWD, even more so after working on this framework. There’s not enough native support for working with media (images, video, etc) which means RWD is still best suited for content heavy sites.

  9. 009 // Jeff L // 03.05.2012 // 2:03 PM

    Jeff, nice stuff here. Thanks for sharing.

    Kev, I needed something like what you’re talking about recently, and I wrote up this script…I’m sure it’s not bulletproof, but worked for what I needed. Allows you to query a css property on an element, and then run certain JS on whether it passed or failed. I was using it mainly in the exact manner you described, which was to test min-width or max-width, in lieu of a media query

  10. 010 // Kev Adamson // 03.05.2012 // 2:40 PM

    Jeff L and Andy: Thanks for those. I’ll definitely bookmark them for future reference.

  11. 011 // freelance web designer // 03.19.2012 // 5:11 AM

    Great work Jeff. It is very hard to design a responsive website. To tell you the truth I have never a never attempted to design a responsive site. But after reading your article I will defiantly have a go.

Tags for this entry