Reputation: 3516
With the new Apple MacBook Pro with retina display, if you provide a "standard" image on your website, it'll be a little fuzzy. So you have to provide a retina image.
Is there a way to automatically switch to @2x
images, like iOS (with Objective-C) does? What I've found is: CSS for high-resolution images on mobile and retina displays, but I wish I could find an automatic process for all my images, without CSS or JavaScript.
Is it possible?
UPDATE
I would emphasize this interesting article suggested by @Paul D. Waite and an interesting discussion about it linked by Sebastian.
Upvotes: 116
Views: 78516
Reputation: 20188
With JSF you could create a custom Facelets tag to save the fuzz of having to add srcset
to each image.
In your taglib.xml
you could have something like:
<tag>
<tag-name>img</tag-name>
<source>tags/img.xhtml</source>
<attribute>
<name>src2x</name>
<required>true</required>
<type>java.lang.String</type>
</attribute>
</tag>
And your tag could look something like:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:fn="http://xmlns.jcp.org/jsp/jstl/functions"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<img src="#{fn:replace(src2x, '@2x', '')}"
srcset="#{src2x} 2x"/>
</ui:composition>
Which could be used like:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:myTag="http://your.com/namespace-of-taglib">
<myTag:src2x="[email protected]"/>
</html>
And will render:
<img src="image.jpg"
srcset="[email protected] 2x"/>
Upvotes: 1
Reputation: 5160
There is a new attribute for the img tag that allows you to add a retina src attribute, namely srcset. No javascript or CSS needed, no double loading of images.
<img src="low-res.jpg" srcset="high-res.jpg 2x">
Browser Support: http://caniuse.com/#search=srcset
Other Resources:
Upvotes: 173
Reputation: 1731
Here is the less mixin I use to achieve this for background images. retina.js doesn't work for background images if you are using dotLess, since it requires its own mixin which itself uses script evaluation which isn't supported in dotLess.
The trick with all of this is to get IE8 support. It can't easily do background-size so the base case (non mobile media query) has to be a simple, non-scaled icon. The media query then handles the case of retina and is free to use the background-size class since retina will never be used on IE8.
.retina-background-image( @path, @filename,@extension, @size )
{
.background-size( cover );
background-image: url( "@{path}@{filename}@{extension}" );
@media only screen and ( -webkit-min-device-pixel-ratio: 2 ),
only screen and ( -moz-min-device-pixel-ratio: 2 ),
only screen and ( -o-min-device-pixel-ratio: 2/1 ),
only screen and ( min-device-pixel-ratio: 2 )
{
background-image:url( "@{path}@{filename}@x2@{extension}" );
background-size:@size @size;
}
}
Usage sample:
.retina-background-image( "../references/Images/", "start_grey-97_12", ".png", 12px );
Ths requires you to have two files:
start_grey-97_12.png
[email protected]
Where the 2x
file is double resolution for retina.
Upvotes: 9
Reputation: 9139
If you are not frustrated by fear of using java-script then here is a good article http://www.highrobotics.com/articles/web/ready-for-retina.aspx. It has very simple solution.
And the example in JSFiddle is worth a thousand words.
Using:
<img onload="getImgSrc(this,'image_x1.png')" width="100" height="100" />
JS:
/* RETINA READY IMG SRC */
function getImgSrc(img, src) {
var srcResult = src;
// if high-res screen then change _x1 on _x2
if (window.devicePixelRatio > 1 &&
src.indexOf("_x1.")>=0) {
srcResult = src.replace("_x1.", "_x2.");
}
img.onload = null; //protect from second rasing
img.src = srcResult;
}
$(document).ready(function(){
// fire onload trigger on IMG tags that have empty SRC attribute
var images = $('img:not([src=""])');
images.each(function(i) {
$(this).trigger('onload');
});
});
Upvotes: 0
Reputation: 3516
I've found this interesting way for providing multiple resolution images.
It actually uses CSS, something I wanted to avoid, and works in Safari and Chrome only.
I'm talking about image-set
.
Here's an example, provided by Apple (here):
header {
background: -webkit-image-set( url(images/header.jpg) 1x,
url(images/header_2x.jpg) 2x);
height: 150px; /* height in CSS pixels */
width: 800px; /* width in CSS pixels */
}
I wanna share also these two links:
Upvotes: 1
Reputation: 404
This problem is especially tricky with responsive sites where and image can be of varying width dependant on browser size. Also when dealing with a CMS where multiple editors are potentially uploading 1000s of images it to me seemed unrealistic for me to ask people to upload specially compressed images.
So I wrote a script that takes this into account, it fires at the bottom of the page and on resize finish. Each time taking into account pixel density and the size the image is occupying.
http://caracaldigital.com/retina-handling-code/
Upvotes: 0
Reputation: 339
Just provide retina images to everyone, and squeeze the image to half its native size inside the image element. Like let's say your image is 400px
wide and tall - just specify the image width as 200px
to make it look sharp like this:
<img src="img.jpg" width="200px" height="200px" />
If your image is photographic, you can probably increase the JPG compression on it without making it look worse, because the JPG compression artifacts probably won't be visible when the image is displayed at 2x
: see http://blog.netvlies.nl/design-interactie/retina-revolution/
Upvotes: 8
Reputation: 1014
There are different solutions, each with its own pros and cons. Which one is best for you depends on various factors, such as how your website is designed, what kind of technology your typical visitors are using etc. Note that retina displays are not limited to the Macbook Pro Retina and the coming iMacs, but also include mobile devices, which may have their own needs.
The problem is also closely related to images in responsive designs in general. In fact, it is probably best to utilize generic responsive design techniques, instead of designing for specific devices. After all, technology will keep changing all the time in the future, too.
Some of the solutions/discussions I noted:
<picture>
tag may become a solution supported by a W3C working group and even Apple.As the other answers show, there are even more techniques - but probably no best practice, yet.
One thing I wonder is how to test and debug some of these techniques, without having the respective device(s) available...
Upvotes: 15
Reputation: 1166
Since no one's mentioned the obvious yet, I'll float it out there: where possible, just use SVG. They appear at beautiful retina resolutions with no effort whatsoever.
Support for it is good with IE8 being the main dinosaur to worry about. Gzipped file sizes are often better than bitmapped (png/jpg) formats and the images are more flexible; you can reuse them at different resolutions and restyle them if necessary, which saves both development time and download bandwidth.
Upvotes: 12
Reputation: 13
if its background images a simple way to do this is:
#image { background: url(image.png); }
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (-moz-min-device-pixel-ratio: 2),
only screen and (-o-min-device-pixel-ratio: 2/1),
only screen and (min-device-pixel-ratio: 2) {
#image { background: url([email protected]); background-size: 50%; }
}
another simple way is to use this method:
Just replace:
<img src="image.jpg" alt="" width="200" height="100" />
with
<img src="[email protected]" alt="" width="200" height="100" />
Upvotes: 1