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 */
}
</style>
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:
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){
body{
font-size: 80%;
}
div#leftcolumn{
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 #### */
div#featuredbox{
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){
div#featuredbox{
-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.