HD & Retina Display Media Queries

Responsive web design has been getting a lot of attention in the last year & rightfully so; if you’re building a website, #RWD techniques are the simplest way to adapt a website to the “constantly in flux” mobile landscape. Of all the techniques involved in creating a responsive design, media queries are the most powerful technique for making drastic changes in your layout & design. I’m not going to go in to detail on responsive design techniques here; there’s already great articlesand books that have been published on “the what & how” of responsive design. However, I recently discovered a #RWD media query technique that I haven’t heard much about and felt like sharing: resolution-specific media queries.

Resolution media queries work just like size threshold (e.g., max-width) media queries, except you’re defining a break-point based on a resolution density. This is extremely useful when you need to get your images & icons looking crisp on high-definition & Retina display devices. The basic syntax is essentially the same as other media queries:

@media only screen and (min-resolution: 200dpi){
/* Resolution-specific CSS & images */
}

For increased specificity for different pixel densities and cross-browser support, utilize the min-device-pixel-ratio properties and dppx (dots per pixel unit) resolution specification:

@media
only screen and (-webkit-min-device-pixel-ratio: 1.25),
only screen and ( min--moz-device-pixel-ratio: 1.25),
only screen and ( -o-min-device-pixel-ratio: 1.25/1),
only screen and ( min-device-pixel-ratio: 1.25),
only screen and ( min-resolution: 200dpi),
only screen and ( min-resolution: 1.25dppx)
{
/* Resolution-specific CSS & images */
}

Where did I get the resolution (200dpi) and min-device-pixel-ratio (1.25) values?

160dpi is considered the baseline for screen pixel density, since it’s a 1:1 screen-pixel to device-pixel ratio. Apple’s Retina display is a 2:1 screen-pixel to device-pixel ratio, which is about 320 dpi (326ppi to be more accurate). If you only want to target Retina displays, then setting min-device-pixel-ratio: 2 & min-resolution: 192dpi should be fine. However, Android supports a range of different dpi devices, including mdpi (160dpi), hdpi (240dpi), xhdpi (320dpi) and anywhere in between. For example, the new Asus Nexus 7 tablet has a 1280 x 800 HD display at 216dpi. Settingmin-device-pixel-ratio: 1.25 & resolution: 200dpi will serve every device with a 25% higher than normal resolution your crisp icons and HD specific CSS (which is the technique I use on this blog).

Background Images & Icons

The trick to serving background images & icons for HD/Retina displays is utilizing the newbackground-size CSS3 property in your resolution media query. Just set the background-size: property’s value equal to the width of the non-Retina image & you’re all set:

/* Normal Resolution CSS */
.logo{
width: 120px;
background: url(logo.png) no-repeat 0 0;
...
}
/* HD/Retina CSS */
@media
only screen and (-webkit-min-device-pixel-ratio: 1.25),
only screen and ( min--moz-device-pixel-ratio: 1.25),
only screen and ( -o-min-device-pixel-ratio: 1.25/1),
only screen and ( min-device-pixel-ratio: 1.25),
only screen and ( min-resolution: 200dpi),
only screen and ( min-resolution: 1.25dppx)
{
.logo{
background: url(logo@2x.png) no-repeat 0 0;
background-size: 120px; /* Equal to normal logo width */
}
}

This trick also works with icon sprites as well; you just need to re-declare the background-position for each sprite image within the media query after the background-size property (just make sure the Retina sprite is exactly 2X the size of the normal sprite). Andreas Norman wrote agreat blog post about sprites & Retina media queries which explains this technique in a bit more detail.

The Future

Resolution media queries are the simplest technique (I’ve seen so far) to get your background images & icons looking crisp on high-definition/retina display devices today, however this technique is not future-friendly. We could easily see higher definition/resolution devices get released to the market in the near future which will require more media queries, more CSS, more images, and…. bleh. This is where SVG (scalable vector graphics) steps up to save the day; one image format that scales appropriately across different device displays.

At the time of this writing, all modern browsers support SVG graphics, including IE9+, Firefox, Chrome, Safari, Opera and mobile Safari on iOS. It’s also supported on Android 3.0+, but withGingerbread (2.3.3) and below holding 75% of the Android OS market and Android OS 52.5% of the entire global smartphone market, it’s hard for me to see SVG as a universal responsive design solution at this time.

There’s also CSS4’s image-set property value, which looks like a very promising solution for handling multi-resolution background images. The image-set value lets you to specify multiple resolution options for the background-image: CSS property, which in theory provides browsers the option to choose the proper image based on their needs (retina vs. normal display, bandwidth restrictions, etc.).

At this time, only iOS6, Safari 6, & Chrome 21 accept CSS4’s image-set value, which is great for supporting Retina displays on those browsers today. However, image-set only accepts 2 values, a 1x (normal) image and 2x (retina) image, which is a bit of a bummer if you want to specifically target HD displays separately from Retina displays. And what about HD Windows Phone, Symbian (Nokia), Blackberry, etc…. ???

I prefer to use CSS3 gradients, box-shadows, and other modern techniques that are currently supported across all device browsers for designing interface elements at this time and until we see a better recommendation from the spec.

References: