Responsive Web Design Using CSS3 Media Queries

Posted by & filed under Front-End Development.

Responsive web design is a type of progressive enhancement that uses fluid grids, flexible-size images and media queries to optimize a website for a users’ specific viewing context. At its core, responsive web design is about adjusting layout, typography and imagery to provide a consistent, device-independent web experience. Fluid grids and flexible size images aren’t new concepts to web design, so I’ll spend most of this post discussing media queries.

There has been a lot of recent debate about whether responsive web designs are a valid alternative to dedicated mobile sites and/or native applications. Some call the practice “fools gold” while others think responsive web design finally lets developers achieve the code-once-for-all-platforms-nirvana we’ve been seeking for so long. In reality, it’s likely neither of the above. But the fact remains that I want my site to look good and be easy to use on mobile devices without having to create a dedicated mobile site. For me, CSS3 media queries are the answer.

The “media” part of media queries isn’t new to CSS. Prior to CSS3 you could limit the scope of stylesheets, but we were confined to a set of media types like print, screen and projection. This was a serviceable solution back when all screens were similarly-sized. But now, since screens vary so greatly in size, it is necessary to further-inspect the media on which a user is viewing a site to determine how best to display the site. Thankfully, the CSS3 specification expands media type-dependent stylesheet support by allowing the use of expressions to further limit the scope of stylesheets. Using CSS3 media queries, we can inspect characteristics of users’ devices, such as size, orientation, resolution and pixel density, and adapt styles accordingly.

Media queries can exist in HTML or @import and @media rules in CSS. As if the name wasn’t a dead giveaway, media queries consist of a media type and a query. Media types include print, projection, screen, handheld, aural, Braille, tty, tv and all. If you’re familiar media types, you may ask why we can’t simply use the handheld type to target mobile devices. Technically you can but the Symbian browser, Opera and mobile Safari ignore the handheld type. According to Apple’s developer guides mobile Safari “ignores the print and handheld media queries because these types do not supply high-end content.”

The second part of media queries, the query, inspects media features to determine when specific styles are used. The most commonly used media features include width, height, device-width, device-height and orientation. Media features that pertain to width and height accept the min- and max- prefixes allowing us to further refine the scope of a particular style. Orientation is calculated by comparing the browser width and height. This makes it possible to query the orientation any device, not just tablets and mobiles.

One additional media feature of interest, device-pixel-ratio, allows inspection of pixel density. Querying this media feature allows you to serve higher-resolution images for the iPhone Retina display. Unfortunately, at the time of this writing, it is necessary to use vendor prefixes so you’ll need to add -webkit and -moz to make this work. Eventually you’ll be able to use just device-pixel-ratio. You can also apply the min- and max- prefixes to device-pixel-ratio.

One of the keys to successfully implementing a responsive web design is determining the resolutions at which your site should “respond”. This highly dependent upon the design of your site but you will likely want your site to respond at (or near) common tablet and mobile device resolutions (1024px and 768px for iPad, 960px and 640px for iPhone 4 and 480px and 320px for iPhone 3GS and older).

So what does a media query look like? It depends on where you put it. As mentioned earlier, media queries can exist in HTML or @import and @media rules in CSS:

Media Query in HTML

<link rel="stylesheet" media="screen and (max-width: 1024px)" rel="stylesheet" href="example.css">

Media Query in @import

@import url(example.css) screen and (max-width: 1024px)

Media Query in stylesheet

@media screen and (max-width: 1024px) { ..styles go here }

The stylesheet I use to achieve my responsive design for this site consists of a set of base styles and three sets of media queries. The base styles apply to all browsers with a width greater than 994px. Browsers that don’t support CSS3 use the base styles as well. There are several options for adding media query support to those browsers, but since the goal of my responsive design is to improve the appearance and usability of my site on mobile devices and tablets (all of which have browsers that support CSS3), I chose not to implement a fallback.

Here are the media queries used in my site:

@media only screen and (min-device-width: 768px) and (orientation: portrait),
screen and (max-width: 994px) { /* for tablets in portrait mode and desktops with less than 994px of horizontal browser width */ }

@media screen and (max-width: 555px),
screen and (max-device-width: 480px) { /* for desktops with less than 555px of horizontal browser width and devices with less than 480px wide (most phones in landscape orientation) */ }

@media screen and (max-width: 320px) { /* anything less than 320px (primarily phones in portrait */ }

In addition to these media queries, I use a viewport meta tag to set the initial scale of the site and disable zooming on mobile devices and tablets. The viewport meta tag looks like this:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

Here’s what my site looks like at various browser sizes:
BrianHadaway.com - Full Size

BrianHadaway.com - Tablet Landscape Orientation BrianHadaway.com - Tablet Portrait Orientation BrianHadaway.com - Mobile Landscape Orientation BrianHadaway.com - Mobile Portrait Orientation

As much as I like responsive web design, there are some valid criticisms of the practice. Responsive web design assumes that there is only one use case for all browsing contexts which is not always the case. For instance, visitors using tablets or desktops may be interested in viewing a retail site’s photo gallery or testimonials, while someone using a mobile device may be solely interested in finding a phone number or store hours. Also, the practice of only using media queries to implement responsive design can result in unnecessary overhead when loading elements that aren’t used in smaller contexts. If a media query for a small mobile context hides a slideshow, the browser still may unnecessarily load the related script and images.

Dedicated mobile sites and native applications may be the right solution for some projects, but responsive web design with CSS3 media queries is a quick and easy way to provide a consistent user experience across all browsing contexts.

4 Responses to “Responsive Web Design Using CSS3 Media Queries”

  1. Ian

    We’re having a problem with a highrez sprite for retina not showing up.

    How can we inspect this, a la firebug or chrome/safari dev tools?

    If there’s a way, soes it work on PC and Mac?

    thanks!
    –ian

    Reply
    • Brian

      @Ian – As you know, the tools for inspecting the DOM in iOS are pretty weak but there are a couple of hacky ways you could solve the problem. I assume you’ve tested that your media query is actually applicable to the iOS/Safari/Retina context. It should looks something like this:

      @media only screen and (-webkit-min-device-pixel-ratio: 2) {
      /*context specific styles go here*/
      }

      You could change the -webkit-min-device-pixel-ratio property to 1 and debug in Chrome/Safari on PC/Mac then switch it back to 2 once you’re done.

      If you want to debug on an iPhone 4 (or the iPhone simulator), you can turn on the Developer Console by going to Settings > Safari > Developer then use JavaScript to dump your css to the console. If you’re using jQuery, on document ready, you can do something like this:

      console.log($(“body”).css(“background-image”));

      If you still can’t get the sprite to load after all that, I’d take a look at the server logs to see if the correct image is being requested and what the response to that request is.

      Reply
    • Pramod Kumar

      I need solution for Mobile (1024px by 720px) and Desktop (1024px by 768px).

      I am using
      @media screen
      and (min-device-width : 320px)
      and (max-device-height : 720px){}

      Please reply,
      What I do?

      Reply

Leave a Reply

  • (will not be published)

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>