Cross Browser Retina/High Resolution Media Queries

fantasai, Ben Frain, and Peter Gasston have all written about this topic before, though I still see a lot developers using verbose media queries for retina/high resolution displays so I figured I would write up my own post.

Most developers are currently writing retina/high resolution media queries similar to the examples below:

This media query example is from 37signals article on retina images and scss. It is based on the one in Thomas Fuchs’ Retinafy book but, it has been modified to define the Google Nexus 7 with it’s 1.3 pixel ratio as a retina-capable device.

@media (min--moz-device-pixel-ratio: 1.3),
      (-o-min-device-pixel-ratio: 2.6/2),
 (-webkit-min-device-pixel-ratio: 1.3),
         (min-device-pixel-ratio: 1.3),
         (min-resolution: 1.3dppx) {
   /* Retina-specific stuff here */
}

Chris Coyier has a retina display media query example that looks like this:

@media  
only screen and (-webkit-min-device-pixel-ratio: 2),  
only screen and ( min--moz-device-pixel-ratio: 2),  
only screen and ( -o-min-device-pixel-ratio: 2/1),  
only screen and ( min-device-pixel-ratio: 2),  
only screen and ( min-resolution: 192dpi),  
only screen and ( min-resolution: 2dppx) {
    /* Retina-specific stuff here */
}  

What’s wrong with the above solutions

Nothing really, though they could be a lot cleaner. A friend asked me about retina media queries and how to get them to work on his new Windows 8 Phone.

It got me thinking about the standard retina/high resolution media query I typically use. Usually I just copy and paste from other sites and had never put much thought into it.

When I tested the query I usually use on his phone, I learned that IE does not have a device-pixel-ratio media query. There is no -ms-device-pixel-ratio. You can’t detect the device-pixel-ration with Javascript using window.devicePixelRatio in IE either. Also of note, window.devicePixelRatio does not currently work in Firefox, though it does work in Opera and Chrome.

IE is using standards, this is new

The device-pixel-ratio is not a standard media query.

-webkit-min-device-pixel-ratio: is not a standard

min–moz-device-pixel-ratio: is not a standard

-o-min-device-pixel-ratio: is not a standard

min-device-pixel-ratio: I don’t think the un-prefixed version works an any browsers, because it’s not a standard.

Ok, so we got that cleared up. Good news is the resolution media query is a standard media query.

I started looking to see which browsers supported the resolution media query. I forked Jordan Moore’s Palm Reader to do some testing specifically related to device-pixel-ratio and resolution media queries. I also looked at MDN’s documentation on resolution media queries and found that it actually has great support.

Resolution media queries are currently supported in IE9+, FF3.5+, Opera9.5+. However, support for resolution media queries is lacking in webkit browsers. Support for resolution media queries was recently added to webkit on Oct. 23rd, 2012.

This means you can replace, the min–moz-device-pixel-ratio, the -o-min-device-pixel-ratio with a resolution media query. You can also just remove the unprefixed min-device-pixel-ratio.

This cleans up Coyier’s retina/high resolution media query.

@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx) {
    /* Retina-specific stuff here */
}

We can clean this up even more though. The dppx unit is a new unit that is equal to the device-pixel-ratio value webkit uses.

However, the dppx unit is not as widely supported as the dpi unit. The dppx unit is supported in FF 16.0+ and Opera 12.10+.

IE does not currently support dppx units.

If you want to support retina/high resolution devices that are running IE, you need to use the resolution media query and use dpi units. If you’re going to use the dpi unit, I don’t see much need to include the dppx unit as well. Everywhere the dppx unit is supported, the dpi unit is also supported. Using both units would be like writing a media query that uses pixels and ems for the same size.

@media
only screen and ( min-width: 320px),
only screen and ( min-width: 20em) {
/* Two units that equal the same value don't make sense in this media query*/ 
/* Why use two units which equal the same value with resolution media queries? */
}

Final retina/high resolution media query

This works in all the browsers that Coyier’s original example does and is just a future friendly.

@media 
only screen and (-webkit-min-device-pixel-ratio: 2), 
only screen and (min-resolution: 192dpi) { 
    /* Retina-specific stuff here */
}

Like I said, others have written about this before, though I still see a lot of people using verbose retina/high resolution media queries. As more Windows 8 devices come out, I can see a need for retina/high resolution media queries that work in IE.

I’ve done some testing across different desktop browsers and this looks to work cross-browser. I need to do some testing on mobile devices to see if the slimmed down media query works as well as it does on desktops. Hopefully this helps other developers see they can slim down retina/high resolution media queries while still having them work on a wider range of devices.

/* Clean version examples */

/* 1.25 dpr */
@media 
(-webkit-min-device-pixel-ratio: 1.25), 
(min-resolution: 120dpi){ 
    /* Retina-specific stuff here */
}

/* 1.3 dpr */
@media 
(-webkit-min-device-pixel-ratio: 1.3), 
(min-resolution: 124.8dpi){ 
    /* Retina-specific stuff here */
}

/* 1.5 dpr */
@media 
(-webkit-min-device-pixel-ratio: 1.5), 
(min-resolution: 144dpi){ 
    /* Retina-specific stuff here */
}

/*2.0 dpr */
@media 
(-webkit-min-device-pixel-ratio: 2), 
(min-resolution: 192dpi){ 
    /* Retina-specific stuff here */
}

Update

I’ve finished my testing on the mobile devices I have access to and the results are interesting to say the least.

I tested on an Android 2.3 device, an Android 4.1, and an iPad 3. I also got my hands on two of the new Windows 8 phones for testing.

The simplified retina/high resolution media query works great across the stock browsers on iOS and Android. -webkit-device-pixel-ratio and window.DevicePixelRatio work great as well as expected. The stock browser on iOS and Android is webkit based browsers so there really is no surprise there.

Things get interesting when looking at how Opera Mini, Firefox for Mobile (Fennec), and IE on Windows Phone 8 handle retina/high resolution media queries.

Opera Mini

On iOS and Android, Opera Mini reported odd values across the board for high resolution media queries and window.devicePixelRatio. I’m guessing this has to do with it being a proxy browser.

On my iPad 3 and my Android 4.1 device, both devices have a device-pixel-ratio of 2. However, when using window.devicePixelRatio, Opera Mini reports the value of 1 on these devices.

In regards to media queries, using Opera prefixed min-device-pixel-ratio media query, only the -o-min-device-pixel-ratio:1 reported true on the iPad 3 and Android 4.1 device. However, the min-resolution:192dpi media query reported true.

The resolution media query is reporting the right value in Opera Mini, but the prefixed -o-min-device-pixel-ratio is not.

Also of interest, only dpi units work in Opera Mini currently.

On my Android 2.3 device, the device-pixel-ratio is 1.5. Again, -o-min-device-pixel-ratio:1 was the only Opera prefixed media query to report true. However, the only min-resolution media query to report true was the one set to 96dpi.

I’m guessing these issues are all caused from Opera Mini being a proxy browser.

Of note, -o-device-pixel-ratio media queries and resolution media queries work create in Opera Mobile on Android. Opera Mobile also supports dpi, dpcm, and dppx units in resolution media queries.

Firefox for Mobile (Fennec)

I tested Firefox for Mobile on my Android devices and saw some of the most bizarre results from testing. On both my Android 2.3 and Android 4.1 devices, the min–moz-device-pixel-ratio: 1 media query was the only moz prefixed media query to report true.

On the Android 4.1 device, which has a dpr of 2, the min-resolution:192dpi and min-resolution:2ddpx reported true. Interestingly, these same two media queries reported true on the Android 2.3 device which has a dpr of 1.5.

It seems like resolution media queries work a bit better than min–moz-device-pixel-ratio media queries in Firefox for Mobile on Android, but both a buggy.

Interenet Explorer on Windows Phone 8

I tested on two of the new Windows 8 phones, the Nokia 920, and the HTC 8x. Both phones do not support any of the device-pixel-ratio media queries. The devices do support the resolution media query, dpi and dpcm units, but not dppx units.

However, both devices reported a resolution of 96dpi. I am not sure if this is correct or not. I’ve seen people say the phone has a high resolution screen, so it seems odd that it only reports 96dpi. If anyone has more info on this, let me know in the comments below.

Retina/high resolution media queries work great across a wide range of different devices and different browsers, though if you really wanted to make your site look great on the widest range of retina/high resolution displays and browsers, I’d look at using icon fonts, SVG images and compressive images.

  • http://schsch.tumblr.com maze

    Thanks for this! I recently looked at a website on my Nexus 7 tablet (which has, according to this thread http://android.stackexchange.com/questions/24922/why-can-the-nexus-7-display-so-much-more-content-on-screen-than-the-galaxy-nexus, a pixel density of 240 dpi although I don’t understand how it can be higher than a retina display) and some graphics looked really bad. The site is http://quote.fm/welcome and the graphic is the logo in the upper left corner. On the iPad 3 it looked great because the browser loaded the retina version of the logo. Not so on the Nexus 7. Any idea how to target the Nexus 7 or comparable devices?

    • Brett

      Thanks maze, glad this was useful. I havn’t tested the Nexus 7 myself, though I believe it’s device-pixel-ratio is 1.3. Both of these sites are saying its dpr is 1.3: http://bjango.com/articles/min-device-pixel-ratio/ and http://37signals.com/svn/posts/3271-easy-retina-ready-images-using-scss

      I would recommend using an SVG image for you logo, the quote.fm site looks great by the way.

      • http://schsch.tumblr.com maze

        Oh, okay. Thank you for the links.
        The quote.fm site is not mine, by the way. It’s just a site I came across where the differences were really apparent.

      • http://friendfeed.com/zoblue zoblue

        On my Nexus 7 (Android v4.2.1), the “Final retina/high resolution
        media query” worked in Firefox Mobile (v17) but not in Chrome
        (v18.0.1-yadda-yadda).

        Also the first two individual media queries (1.25dpr & 1.3dpr) underneath the main one did work in Chrome and all four worked great in Firefox. Go figure! :)

  • http://twitter.com/marcnischan Marc Nischan

    Well done, Brett! I read Chris’ post and it looks like he has updated it to match your research. Hats off to you both.

    So, let me ask you this: how do you split up your media queries? It is a common practice to write the mobile first, then the “medium” and “large” segments after at the bottom of the style sheet. Are you writing these in the flow of the styles now, rather than in “silos” like I described? It seems like you would have to in order to control how these different breakpoints select which images to display.

    Thanks for the great info!

  • http://rolling-webdesign.com/ Theo

    Great article, will follow your advice, thanks for sharing!

  • grapplerulrich

    This is what WordPress is using at the moment.
    @media print,
    (-o-min-device-pixel-ratio: 5/4),
    (-webkit-min-device-pixel-ratio: 1.25),
    (min-resolution: 120dpi) {}
    http://core.trac.wordpress.org/changeset/22629

  • Brenton Taylor

    hi there, i am having trouble with my @media query for my website. i can’t seem to get the retina images to display. it might be to do with the location of the file, but as i am new to @media query, i don’t know if it is just. can some one point me in the right direction please or respond who has dealt with this issue before. Thanks

  • http://twitter.com/ckhicks CK Hicks

    Beautiful work, this really eliminates a lot of the mucking about in hyperspace. Thanks for all your hard work and research!

  • kamranayub

    I just came across this because I’m having this exact issue with my 8X. It’s only responding to 96dpi, not a unit more. It doesn’t make sense because it has a 341ppi screen, so the pixel ratio should definitely be more than 1.3 (124.8dpi).

    ARGH.

    I will have to research more.

    • http://twitter.com/bjankord Brett Jankord

      Mike Stow has done some recent research, and while it seems IE10 supports resolution media queries, on Windows 8 phones (and possibly tablets?), IE is reporting 96dpi incorrectly. This causes an issue because you then can no longer rely on media queries to determine if you should serve high resolution images.

      I think if you want graphics that don’t look blurry on Windows 8 phones, it would be better to use SVGs if your image is not a photo. That’s the solution my friend used to fix the blurry logo he was seeing on his website when viewing it on his Windows 8 phone.

      Another solution is to always serve high resolution images with the compressive image technique. http://filamentgroup.com/lab/rwd_img_compression/

      • kamranayub

        Compressive images is certainly the way we’d like to serve photos on our site, but we’re using PNG sprites for icons or other artwork. In any case, it’s too late for the current project I’m on, since I’ve only just discovered this issue and we’ve already done a ton of work creating retina-ready images. We already decided against SVG before this due to extra time involved (and other things).

        So basically the only thing I can do right is… nothing. I’m OK with that right now, I just wanted to know what was going on to note it for the future.

  • http://twitter.com/beholdr Alexandr Shabunevich

    Well, I just tested your minimal media queries and can said that on desktop Opera 12.12 (retina MBP) it doesn’t work. You need to add Opera rules for desktop, like this:

    @media only screen and (-webkit-min-device-pixel-ratio: 1.5),
    only screen and (-o-min-device-pixel-ratio: 3/2),
    only screen and (min-resolution: 144dpi) {

    }

  • http://www.svachon.com/ Steven Vachon

    Awesome! Thanks for this. I just grouped all conditions together into a single @media query. That way, regular screens are served smaller pixel-perfect images (great for icons) and all “retina” screens are served 2x larger images scaled to fit with background-size.

  • Guest

    jpojopk

  • http://front-endmagazine.com/ Frontend Magazine

    Great Article! Thanks a lot.

  • jrista

    The Nokia Lumia 920 phone has a resolution of 332dpi, so a reported resolution of 96dpi is almost 3.5 times TOO SMALL! I believe most of the newer Android phones, and for sure the iPhone, also have resolutions that are well over 300dpi (326dpi for iPhone 4/5, and 441dpi for Galaxy S4). I think this is a fairly significant area where browsers dishing out a canned 96dpi is a truly useless thing. Knowing screen dimensions as well as actual resolution in dpi/dpcm/ppi/ppcm is going to become a critical thing in the future to ensure proper device scaling of responsive web designs.