With the ubiquity of mobile devices, it was only a matter of time before CSS caught up to provide a means of targeting devices by screen size and/or by feature. Now, with media queries, that day has come. That’s the good news. The not-so-good news is that mobile devices have become so varied and versatile that it makes our job of targeting specific ones an ever-evolving side job. In practical application, developers often find themselves endlessly tweaking their media queries to weed out certain exceptions and special cases. I know because I’ve been there. If you’re looking to present page content to suit the device that it’s viewed on, this article will help you avoid some of the common mistakes that CSS media rookies make so that you can have your rules work the first time…or at least by the second or third time!
Introducing Media Queries
You may have already used CSS media queries without realizing it if you’ve ever created rules for printing by including the @media keyword. Part of the CSS2 spec, they allowed you target specific media types:
<style> @media screen { p.test {font-family:verdana,sans-serif;font-size:14px;} } @media print { p.test {font-family:times,serif;font-size:10px;} } @media screen,print { p.test {font-weight:bold;} } </style>
CSS3 introduces the ability to apply your CSS rules to specific devices, screen & page dimensions, orientations, and more. For instance, to apply CSS specifically to mobile phones, we would define the following block:
@media only screen and (max-device-width: 480px) { }
Browser Sniffing Is Out, Media Queries Are In
Media queries replace the browser sniffing practices of old and are a notable improvement over the former. Since browsers may (and do) spoof other browsers, relying on header information is unreliable at best! Testing for specific features is a far superior solution. To recap, don’t do this:
if( navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || ){ // Send Mobile Site }
If your site does use browser sniffing to determine the device type, update it.
Here’s a more concrete media query example that governs the styling of a logo image on both “full-size” devices such as desktops and laptops as well as mobile ones:
#logo { background: url(images/logo.png); width: 650px; border: 1px #ccc solid; } @media only screen and (max-device-width: 480px) { /* define mobile specific styles come here */ #logo { background: url(images/logo_mobile.png); width: 400px; } }
Rules within the media query will override the default ones where applicable. Those that are over-written, such as the border property, should be applied to both mobile and non-mobile devices.
I employed a similar media query was employed to create different menu section expanders on a site that I recently worked on. First, here’s the full-size page:
Mobile devices present a more compact version of the page:
What You Can Test For
Device-width may be the most widely tested feature in media queries, but is certainly is not the only one. The following table shows all of the widely accepted features along with accepted values and whether or not they accept the min- and max- prefixes:
Feature | Value | Accepts min/max prefix | Description |
---|---|---|---|
width | length | Yes | The width of the targeted display area (ie: the browser window on most desktop and mobile devices). On desktop computers, if the user resizes the browser, the width changes as a result, while on most mobile browsers, the inability to resize the browser window means it will stay constant. |
height | length | Yes | The height of the targeted display area (ie: the browser window on most desktop and mobile devices). |
device-width | length | Yes | The width of the device’s entire screen irrespective of the browser window’s width. On a desktop with screen resolution 1024×768 for example, the device-width is always 1024. On an iPhone -including iPhone 4- the device-width is 320. |
device-height | length | Yes | The height of the device’s entire screen. On a desktop with screen resolution 1024×768 for example, the device-height is 768. On an iPhone- including iPhone 4, the device-height is 480. |
orientation | “portrait” or “landscape” | no | The orientation of the device. When the device’s “width ” media is larger than its “height “, the orientation value returned is “landscape “, otherwise, it returns “portrait “. |
aspect-ratio | ratio | yes | Detects the ratio of value of the "width" media to the value of the "height" media, such as 2/1 |
device-aspect-ratio | ratio | yes | Detects the ratio of value of the "device-width" media to the value of the "device-height" media. On a device with screen resolution 1280×720, the following device-aspect-ratio values would all match it (multiples of 1280×720):
@media screen and (device-aspect-ratio: 16/9) { } @media screen and (device-aspect-ratio: 1280/720) { } @media screen and (device-aspect-ratio: 2560/1440) { } |
color | integer | yes | Number of bits per color component of the device. If the device is not a color device, the value is zero. |
color-index | integer | yes | Number of entries in the color lookup table of the output device. |
monochrome | integer | yes | Number of bits per pixel in a monochrome frame buffer. For non monochrome devices, this value is 0. |
resolution | resolution | yes | The resolution of the output device, or the density of the pixels. Common units are “dpi” and “dpcm”. |
scan | “progressive” or “interlace” | no | The scanning process of “tv” output devices. |
grid | 1 or 0 | no | Detects whether the output device is grid or bitmap. Grid based devices return a value of 1, all others a value of 0. |
So where would we use all of these attributes? Any time that our goto device-width property isn’t enough. For instance, since content in most mobile devices can be viewed in either portrait or landscape orientation, it makes sense to present your pages in a different format for each. The following CSS targets all small screen devices but in portrait mode only:
@media screen and (max-device-width: 480px) and (orientation: portrait){ /* some CSS here */ }
Splitting Up Your Style Sheets By Device
Media queries can be applied to the <link> tag via the media attribute in order to load a different style sheet based on the device type and/or features:
<link href="mobile.css" rel="stylesheet" type="text/css" media="only screen and (max-device-width: 480px)" />
On a small site, it’s helpful to put them after any styles you want to overwrite for easy reference. However, as your site grows, it won’t be long before there will be way too much CSS to sift through. When that time comes, it makes sense to separate your files by device.
Conclusion
Even with all of the enhancements to media queries, some mobile devices such as the new iPhones, Android, and Windows Phone 7 are so versatile that we need to use special workarounds to target them properly. We’ll cover those in an upcoming article.