Introduction to CSS Media Queries

Updated: February 5th, 15'

The last few years have bared witness not only to major changes in the technologies that power the net, but also the devices that access it. With the myriad of smart phones and tablets of all sorts riding the internet wave, as webmasters, gone are the days where our primary concern is just with the optimal screen resolution to design our sites for. These days there are a lot more variables to content with, from the numerous- mainly small - screen sizes of hand held devices to the screen orientation (whether portrait or landscape) of a device. With that in mind comes CSS Media Queries, a nifty CSS feature that builds upon CSS Media types of CSS 2.1 to allow you to easily limit the application of your CSS to specific devices, screen and page dimensions, orientations, and more.

3 ways of inserting CSS media queries

CSS media queries can be added to CSS in all of the ways you're able to define it:

External stylesheet:

<link rel="stylesheet" type="text/css" href="smallscreen.css" media="only screen and (max-width: 480px)" />

Imported stylesheet within the <style> element:

@import "smallscreen.css" only screen and (max-width: 480px);

Within the <style> element as a media rule:

<style type="text/css">
  @media only screen and (max-width: 480px){
    /* rules defined inside here are only applied to browsers that support CSS media queries and the browser window is 480px or smaller */

In all of the above cases, the respective stylesheet will only be applied in the browser when the current browser window is 480px or below, AND only if the browser supports CSS media queries. The later inexplicit condition is due to our use of "only" inside the media query- more on this below.

Browser support for CSS media queries

Browser support for CSS media queries is nothing to get depressed about, found in almost all of the mobile browsers current and past, and for desktop browsers, the current generation at the very least:

CSS media queries support FF IE Chrome Safari Opera iOS Safari Opera Mobile Android browser
  3.5+ 9+ All known versions 4+ 9.5+ 3.2+ 10+ 2.1+

On mobile devices where CSS media queries really saves the day when it comes to designing mobile compatible web pages, it is supported across the board.

It's important to note that while CSS media queries are supported only in more modern browsers, the @media rule itself (without the media queries portion) is recognized by a much larger set, such as IE6. They all support the more basic version of @media in the form of CSS media types that let you confine your CSS to specific mediums, such as @media print to apply your CSS only when the page is printed. It's when you start adding CSS media queries to the @media rule that legacy browsers will then no longer recognize. Consider the following examples:

<!-- This stylesheet is downloaded and rendered by all known browsers, including IE5,6,7 etc -->
<link rel="stylesheet" type="text/css" href="example.css" media="screen" />

<!-- This stylesheet is downloaded and rendered by CSS media query capable browsers, due to the presence of "only" -->
<link rel="stylesheet" type="text/css" href="example.css" media="only screen" />

<!-- This stylesheet is downloaded and rendered by CSS media query capable browsers, due to the presence of "and (min-width: 800px)" -->
<link rel="stylesheet" type="text/css" href="example.css" media="screen and (min-width: 800px)" />

Both the 2nd and 3rd stylesheets above are only downloaded by CSS media queries capable browsers, since the 2nd stylesheet contains the keyword "only", and the 3rd the "and ...". With that said, be careful not to place general CSS rules that affect basic accessibility of your page inside @media rules that use media queries, as they will be ignored by browsers that don't support media queries, potentially breaking the page for them. CSS media queries should be implemented just like any other progressive feature, on top of an existing foundation that has broader compatibility with browsers.

Detectable media features

Time to talk about the "media queries" portion of CSS media queries, in other words, the conditions we can screen for. As of time of writing, below lists the detectable media features:

CSS Media Features
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 1024x768 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 1024x768 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 1280x720, the following device-aspect-ratio values would all match it (multiples of 1280x720):
@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.

You can use logical operators such as "not", "and", "or", and "only" to combine multiple media features in your detection. Lets see some examples now:

/* #### CSS that's applied when the viewing area's width is 765px or less #### */
@media screen and (max-width: 765px){
    font-size: 80%;

    display: none;

/* #### CSS that's applied when the viewing area's width is between 640px and 1600px, all mediums #### */
@media (min-width: 640px) and (max-width: 1600px){
 /* some css here */

You can also target more than one set of media queries at once, by separating each one with a comma:

/* #### CSS that's applied if there is a match for any of the two media queries #### */
@media screen and (min-width: 1280px), print and (min-resolution: 300dpi){
 /* some css here */

The comma behaves similarly to the "OR" operator. Now that we've gotten the basic theory out of the way, it's time to look at how to use CSS media queries in the real world to deploy multiple versions of your webpage that target different devices and screen dimensions.

Using CSS media queries to target different devices and screen dimensions

iPhones, iPads, Android tablets, TVs, and oh yes, the PC. Just a few years ago it was hard to imagine anything other than your bulky desktop or laptop at best travelling the information highway, but nowadays, those devices seems to be more and more in the minority. CSS media queries lets you quickly target different devices in your CSS, primarily through the window/screen dimensions of these devices.

- Targeting "small screen" devices

To kick things off, you can use the below to target "small screen" devices:

/* #### target mobile devices with max device width 480px #### */
@media screen and (max-device-width: 480px){
 /* some css here */

Here the contained CSS rules will only be applied to devices with a width of 480px or less. I'm using max-device-width here instead of device-width intentionally to better target only mobile devices (rather than PCs as well for example). Why? because device-width refers to the width of the device itself, and not just the width of the display area (ie: the browser) that can be changed if the user resizes this display area. Unless your PC has a screen resolution of 480px across or less (not exactly a common sight!), our media query above will not match it, leaving us mainly just with mobile devices. I'm also using the value "480px" for a reason here, as it seems to capture the majority of smart phones at the moment. iPhone and iPhone4 report a device-width of 320, while Android smartphones can go all the way up to 480px such as the Samsung Galaxy II. Mobile devices with a larger device-width probably don't fall under "small screens" anyway to us.

- Targeting Apple mobile devices with high resolution displays (ie: iPhone4+ and iPad3+)

Apple introduced the idea of "retina display" in some of its latest devices such as iPhone 4 and iPad3. Essentially these devices report the same device-width as its predecessors (320px and 768px respectively), but cram two device pixels into each CSS pixel, resulting in double the screen resolution. To target these devices then, Apple supports a proprietary property called -webkit-device-pixel-ratio that returns the pixel density of its device. Both the iPhone 4 and iPad3 return a value of 2:

/* #### CSS for high resolution devices in general #### */
@media screen and (-webkit-min-device-pixel-ratio: 1.5){
  /* some css here */

/* #### CSS for small screen high resolution devices such as iPhone 4 #### */
@media screen and (-webkit-min-device-pixel-ratio: 2) and (max-device-width: 480px){
  /* some css here */

/* #### CSS for large screen high resolution devices such as iPad 3 #### */
@media screen and (-webkit-min-device-pixel-ratio: 2) and (min-device-width: 768px){
  /* some css here */

The above code brings up two additional points. First, CSS media queries currently doesn't support nesting, meaning you cannot put the 2nd and 3rd @media rules above inside the 1st one and do away with the redundant media queries (screen and (-webkit-min-device-pixel-ratio: 2)) in the later. Secondly, CSS media rules like other CSS rules follow the order of cascade when it comes to precedence, so the further down a rule is defined relative to its peers, the higher the precedence.

So what can be optimized for "retina display" devices? Images are a popular choice, as they are perfect candidates to take advantage of the higher resolution. The idea is to serve up two different versions of an image depending on the device, with the one for "retina" devices being double the size and resolution of the original. When actually serving up this hi-res image, we constrain its dimensions to be the same as the original's, allowing retina devices to show 2 pixels for every pixel shown with the original image, resulting in an ultra clear image. Lets do this for a background image as an example:

/* #### normal background served to browsers #### */
  width: 90%;
  height: 400px;
  background: url(original_background.jpg) center center no-repeat;

/* #### CSS for retina devices with larger screens #### */
@media screen and (-webkit-min-device-pixel-ratio: 2) and (min-device-width: 768px){
    -webkit-background-size: 50% auto; /* shrink image to 50% of its actual dimensions, matching that of the original image's above */
    background: url(highres_background.jpg) center center no-repeat; /* high res image that's double the size/ resolution of the original's */

- Targeting devices in "landscape" and "portrait" modes

As if dealing with varying screen sizes isn't enough, we also have to contend sometimes with the orientation of the device. If that's the only thing you're screening for, the CSS media query is simple enough:

@media screen and (orientation: portrait){
  /* some CSS here */

This would target all devices whose browser's height is longer than its width, including on desktop computers. On mobile browsers, this is true whenever the user rotates the screen to, well, "portrait" mode. In real life situations, you'll probably want to further refine your test, such as whether the user is also using a small screen device where orientation matters more:

/* #### CSS to apply to small screen devices in general (whether portrait or landscape mode) #### */
@media screen and (max-device-width: 480px){
  /* some CSS here */

/* #### CSS to apply to small screen devices in portrait mode only #### */
@media screen and (max-device-width: 480px) and (orientation: portrait){
  /* some CSS here */

At this point you may have noticed that we've switched between using "width" and "device-width" in our CSS media queries, seemingly arbitrarily. To a certain extent it is, but not completely. Lets examine the finer distinction between "width" and "device-width" next.

width versus device-width