Serving high res images to retina display
Why setting for Retina
iPhone 4s, iPhone 5, iPad3, iPad4, Macbook 15", Macbook 13" all use Retina display.
Android also support high resolution display, as well as Windows 8(Lumia 920) as mentioned by @JamWaffles.
Adding high resolution support is good for user experience but it definitely add load for developer, as well as bandwidth for mobile. Somebody don't suggest doing that.(Peter-Paul Koch, see the bottom "further reading")
Breifing
There are two methods to implement this function. One is Javascript and the other is CSS. All current solutions are for Retina, but could extend to Android high resolution easily.
CSS solution is about Media Query and -webkit-min-device-pixel-ratio
or -webkit-device-pixel-ratio
- Simple to use.
- Apply to all browsers.
- Disadvantage: Good for background. Harder for
<img>
tag
Javascript solution is about window.devicePixelRatio
property.
- Advantage: Javascript could manipulate image source. So, if you are going to serve direct image instead of background, better to use Javascript
- Could not apply to all browsers but current support is good enough. See below for list.
- Need a bit more setting.
CSS Solution
For normal images, say an icon
.sample-icon {
background-image: url("../images/sample-icon.png");
background-size: 36px 36px;
}
For Retina, add those below
@media only screen and (-webkit-min-device-pixel-ratio: 2), /* Webkit */
(min-resolution: 192dpi) /* Everyone else */ {
.sample-icon {
background-image: url("../images/sample-icon-highres.png");
background-size: 18px 18px;
}
You can use min-resolution: 2dppx
to replace min-resolution: 192dpi
, for those who don't want to remember numbers
Note the difference:
- Two different icons, one normal, one high res. High res icon is double size than normal one.
- The background size. The later is half. But you need test it in your real use.
Resource:
+ http://www.w3.org/blog/CSS/2012/06/14/unprefix-webkit-device-pixel-ratio/
+ http://view.jquerymobile.com/master/demos/widgets/buttons/#CustomIcons
Javascript Solution
Use window.devicePixelRatio
property to detect resolution.
if (window.devicePixelRatio >= 2) {
alert("This is a Retina screen");
//Do something to manipulate image url attribute
//for example add `@2x-` before all image urls
}
Browser SupportSafari, Android WebKit, Chrome 22+ and on Android, Opera Mobile, BlackBerry WebKit, QQ, Palm WebKit,
Ref: http://www.quirksmode.org/blog/archives/2012/06/devicepixelrati.html
For Android
Android device use 1.5 as high resolution instead of 2 in Retina.
http://developer.android.com/guide/webapps/targeting.html --#Targeting Device Density with CSS, #Targeting Device Density with JavaScript
Further Good Reading
http://www.quirksmode.org/blog/archives/2012/07/more_about_devi.html
"I’m not a big fan of serving special retina images because it makes the web too heavy — especially over a mobile connection. Nonetheless people will do it." -- Peter-Paul Koch
Update 2013-04-18 Update jQuery mobile link
Retina displays, high-res background images
Do I need to double the size of the .box div to 400px by 400px to
match the new high res background image
No, but you do need to set the background-size
property to match the original dimensions:
@media (-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.box{
background:url('images/box-bg@2x.png') no-repeat top left;
background-size: 200px 200px;
}
}
EDIT
To add a little more to this answer, here is the retina detection query I tend to use:
@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) {
}
- Source
NB. This min--moz-device-pixel-ratio:
is not a typo. It is a well documented bug in certain versions of Firefox and should be written like this in order to support older versions (prior to Firefox 16).
- Source
As @LiamNewmarch mentioned in the comments below, you can include the background-size
in your shorthand background
declaration like so:
.box{
background:url('images/box-bg@2x.png') no-repeat top left / 200px 200px;
}
However, I personally would not advise using the shorthand form as it is not supported in iOS <= 6 or Android making it unreliable in most situations.
CSS for high-resolution images on mobile and retina displays
In your HTML, create a <div>
like so:
<div class="ninjas-image"></div>
And in your CSS, add:
.ninjas-image {
background-image: url('ninja-devices.png');
width: 410px;
height: 450px;
}
@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) {
.ninjas-image {
background-image: url('ninja-devices@2x.png');
background-size: 410px 450px;
}
}
The magic here is in the CSS @media
query. We have a double-sized image (ninja-devices@2x.png) that we sub-in when the device reports a ‘device pixel ratio’ of 1.5 (144 dpi) or more. Doing it this way allows you to save on bandwidth by delivering the original, smaller image to non-retina devices, and of course it looks great on retina devices.
Note:
This answer was updated in 2016 to reflect best-practice. min-device-pixel-ratio
did not make it in to the standard. Instead, min-resolution
was added to the standard, but desktop and mobile Safari don't support it at the time of writing, (thus the -webkit-min-device-pixel-ratio
fallback). You can check the latest information at: http://caniuse.com/#feat=css-media-resolution.
Optimizing website images for Retina display
In the future, you might be able to use the picture element. In the meantime, the only approach I've seen that might work is to:
- Put a div or span where you want the image. Style it to have the dimensions and layout of the image. Add some kind of identifying mark to it so you can find it (e.g.
class="retina-image"
) - Store information about the different sizes of images you have on or in the element (e.g. using
data-something
attributes) - Put a
<noscript><img src="..." alt="..."></script>
inside the div - On DOM ready:
- use JS to find all the elements with the identifier from step 1
- detect the type of image you want
- find the attribute that tells you what URL to use for that image
- add the image to the DOM inside the container from step 1
This is the approach used by the picturefill library.
Related Topics
How to Detect When a New Element Has Been Added to the Document in Jquery
Invert Colors of an Image in CSS or JavaScript
React Native Flexbox - How to Do Percentages || Columns || Responsive || Grid etc
How to Get Display:Table-Cell Support in Ie? Any Pure JavaScript or Jquery Workaround
Webfonts or Locally Loaded Fonts
Slow Response When the HTML Table Is Big
How to Apply Title Case in Input Box Through CSS
How to Compute Facebook Graph API Cover Offset_Y to Pixel
How to Remove the White Border from Chart.Js Pie Chart
Full Screen Canvas on Mobile-Devices
Remove Specific HTML Tag with Its Content from JavaScript String
How to Do Anything About "Repaints on Scroll" Warning in Chrome for "Overflow:Scroll" Div
Select Element by CSS Style (All with Given Style)
Something Similar to Treegrid in Jqgrid
Find Unused Images, CSS Rules, Js Script Blocks
Calling JavaScript from Function from CSS