Display HiDPI / Retina Images Using Transforms

Problem

There are many ways to display pixel-doubled images on HiDPI/Retina displays. This one uses Craft’s image transforms and a cookie that gets set on the first page view.

Solution

First you need to download and install the LJ Cookies plugin. Craft’s built-in request.getCookie() method won’t read cookies set on the front-end for security reasons.

Next, create two asset transforms. The first, “thumb”, is the size you want the image to appear. The second, “thumb2x”, is exactly twice as big. Obviously you can change “thumb” to whatever makes sense in your case.

Then add the following code to your main JS file:

// Store the pixel ratio in a cookie for use in templates
var hidpi = window.devicePixelRatio >= 1.3 ? 1 : 0;
document.cookie = 'hidpi='+hidpi;

Finally, in your template you need to retrieve that cookie and output the appropriate image file:

{% set imageTransform = craft.lj_cookies.get('hidpi') ? 'thumb2x' : 'thumb' %}
{% set image = entry.photo[0] %}
<img src="{{ image.getUrl(imageTransform) }}" alt="{{ entry.title }}" width="{{ image.getWidth('thumb') }}" height="{{ image.getHeight('thumb') }}">

Discussion

The benefit of this method is that each image file is only downloaded once (unlike methods that download the low-res image first and then replace it with the hi-res version after page-load). The downside is that the first page view won’t get the retina versions. How important that is depends on your site. If you have an image-heavy landing page, it’s not ideal. On an e-commerce site or image-heavy blog, where the interior pages are what is most important, it works great.

One caveat: this method only works with images stored in an Asset field, not those embedded in a rich text block.