b-roll: Andy is making all sites work on all devices.

Here at OpenPlans, we build a lot of web apps with full-screen maps as the primary UI. This is a particularly interesting design challenge when you consider the plethora of mobile devices, tablets, and monitors out there. We want the citizens using our apps to have a rewarding experience, regardless of screen size. How do you do that? You design your an app for no particular device.

Now, the design community knows this. They've communicated it to clients, managers, advertisers, and everyone determined to get their content up high on the page: “There is no fold.” But I'd like to take that even further and suggest a new mantra: “There is no device.” In today's web environment—and more importantly tomorrow's—there are innumerable devices, each with its own screen size, resolution, and capabilities. To build accessible web apps we must design for no device.

Of course, one way of doing this is through CSS Media Queries. But I think many tutorials get it wrong by querying for smaller screens and overriding styles that target larger screens. Instead, default styles should target small screens (mobile first!). Larger screens can then be progressively enhanced via media queries. Here's a better way to structure mobile-first CSS:

/* Default [Mobile] Styles */
.element { … }

/* Tablet Styles */
@media only screen and (min-width: 480px) {
.element { … }
}

/* Desktop Styles */
@media only screen and (min-width: 768px) {
.element { … }
}

The default styles make an element look great and function perfectly on mobile (small screens, actually; we're not doing any user-agent detection). Then, with a media query we override those styles to customize the element for tablets or slightly larger screens. And then again, we override those styles for desktop/large screens.

Let's take a look at how some recent OpenPlans projects have used this CSS structure (resize your desktop browser window to see the results).

CTfastrak Map – Default styles collapse the map legend and navigation menu for small screens (with a bit of javascript to toggle them open), but the legend and menu are always visible on larger screens.

cibi.me – Plan a bike trip and notice how small screens are presented a simplified UI, but larger screens are enhanced with detailed pick-up/drop-off information, a triangular slider to adjust trip parameters, and social buttons to share the planned trip.

Bonus: Thoughts on Conditional JavaScript & CSS Media Queries

So, this mobile-first CSS structure is nice. But it doesn't speed up page loads for smaller screens. Mobile devices still load everything and displaying it accordingly. It's possible to load content conditionally via Javascript. But I'm not a fan of user agent detection. What does intrigue me is loading specific content based on which media queries are being used.

What if we put some content in a pseudo element that's never seen, but JavaScript can read?

body:after {
content: "mobile";
display: none;
}
@media only screen and (min-width: 480px) {
body:after {
content: "tablet";
}
}
@media only screen and (min-width: 768px) {
body:after {
content: "desktop";
}
}

Then we could use JavaScript to detect what the media queries are doing…

var layout = window.getComputedStyle(document.body,”:after”).getPropertyValue(“content”);

…which allows us to load content for specific screen sizes.

if ( layout == "desktop" ) {
// load desktop content…
}

This directly ties the conditionally-loaded content to the page layout. How many uses can you think of for that? Kinda makes me wanna roll my own JavaScript MVC framework.

b-roll is an ongoing series on the OpenPlans blog.

We’ll be giving you updates on in-progress work across our projects, straight from the floor.