Improving your site using retina-optimized images with RetinaJS

Improving your site using retina-optimized images with RetinaJS

Now several years into my professional web development career, I can say that while the quality of your written code will define who you are as a professional among your peers, the "everyday joes" that come to your site are not going to care if your code is indented correctly or if you use the latest DRY implementations. What the typical user cares about is design and user experience; does your website look pretty and ultimately fulfill their needs as a user. If the answer to this question does not return a resounding "yes," then your website or application is effectively broken to these individuals.

I think we can all agree that user experience within a site or application is the absolute paramount item that we as interactive designers should be concerned about. But for the sake of this article, that topic lies beyond our scope of conversation. We are here to talk about the aesthetics that make a site attractive and pleasing to the eye.

Using images to your advantage or disadvantage

As we progress through the development of a new site or application, what can easily set a site above another is the quality and composition of the site's photography. An environment that is designed somewhat poorly can overcome enormous short-comings if the site incorporates quality photographs. Cost aside (since we all know this isn't cheap), this is the quickest and easiest way to improve a site.

Excellent photos don't just lend themselves to composition, lighting, color, etc. Showing these images in the incorrect size and/or resolution can quickly render the image useless if the photo appears grainy or blurred. This is why a team can greatly benefit from close communication between the developers and creatives making sure the correct images are being utilized in the best way possible. Even an uneducated user can identify an image that looks out of place. This is why it is our responsibility as creative professionals to relieve the user of these burdens.

Utilizing the technology evolution to our benefit

If you are designer or front end web developer, I'm sure you are familiar with the 72 dpi doctrine that was drilled into us at school. The instructors preached till they were blue in the face that 72 dpi (dots per square inch) was the best way to render an image without sacrificing quality or load speed. Any other way was useless and over-kill.

Fortunately this is no longer the case.

Up until the last few years, all computer monitors and mobile device screens did not have the ability render high quality images simply because they did not have the pixel density to show anything above 72 dpi. So it was essentially pointless to use anything above 72 dpi within a site; especially with the inherited file size increases as with its respective page load speed.

Thanks to the folks over at Apple for their retina screens and Samsung for their AMOLED screens, we now have the technology to incorporate high density monitors and screens on our devices; allowing us to reap the benefits of high resolution images and animation frame rates above 24 frames per second. All of these new advancements provide a richer experience for all users alike.

Retina images simply put

So now we can support these high density images, but how do we show them? If you regard Apple's documentation on how to automatically swap out these images, we can control which images appear with simple filename suffixes such as @2x or @3x. That's it! The browsers and operating system will take care of the rest.

It is worth noting that @3x was recently introduced thanks to the new iPhone 6/7+ and iPad Pro product lines.

So lets say for a second that we have a image named main-logo.png. The browser/application would show this image as is, regardless of the device that we were using to view this image. Now if we were to include another image, one that is exactly twice the dimensions of the original, within the same location our main-logo.png was located and it was named main-logo@2x.png, the browser/application would know to render this image if a high density screen was being utilized.

Why use a Javascript plugin like RetinaJS

So I'm sure you could be asking yourself at this point, if the browser or device is so smart to automatically swap out the images, why do we have to include a third-party plugin like RetinaJS? Well the answer is somewhat complicated so I've outlined a few points to simplify it for you:

  1. Browser Support - While your computer or phone may support this functionality natively, not all browsers will perform these image swaps for you. This plugin will fire after the page's initial load, quickly combing through the page to swap out the appropriately tagged images to their high resolution counterparts.
  2. Responsive Design - Assuming that anything that we will be building will need to be responsive, all images incorporated into our pages need the ability to grow and/or shrink freely based on the screen size the page is viewed on. This posses a problem when you are effectively doubling or tripling the size of the image after page load. Our Javascript plugin will set a height and width attribute of the original image before swapping its source to prevent any unnecessary expansion.
  3. Page Load - I think we can all agree that when you increase the size of an image, whether its the density or the dimensions, the file size of the image grows with it. It's simple math. I think that we can also agree that if you are cumulatively increasing all of the images across your page and site, the site will not load as fast. Utilizing such a plugin that fires after page load will help spread the load time over a longer period. This means your site will load as it normally would initially, then swapping out the high resolution images once the page is ready for them.

How to use RetinaJS

Using the plugin is ultimately very easy; regardless if you are building an application or CMS-powered website. Whats more is that you have a few different options available to you to call RetinaJS to swap out your images.

Include the plugin

First things first, you include the plugin within your technology stack via minification, or simply by direct injection:

<script type="text/javascript" src="/scripts/retina.js"></script> 

Option 1 - Pre-processed stylesheet

I will make the assumption that you will be using something like SASS/SCSS or LESS to quickly scaffold your sites stylesheets. Thankfully RetinaJS comes with some mixins to be able to automatically swap out your background images, like so:

#logo {
  .at2x('/images/my_image.png', 200px, 100px);

This would then compile to something like this:

#logo {
  background-image: url('/images/my_image.png');

@media all and (-webkit-min-device-pixel-ratio: 1.5) {
  #logo {
    background-image: url('/images/my_image@2x.png');
    background-size: 200px 100px;

The media query beneath the logo ID is the key. Basically its looking for any kind of media, regardless of its type, then looks at the media density and then applies addition CSS to the classification. Also pay special attention to the background size. This locks in the image size and will prevent the image from growing unnecessarily like I referenced to above; thus increasing the pixel density as a result.

Option 2 - Image/Element data attributes

If you are building a website on a CMS, this is probably the best solution for you.

The other option you have available to you is simply incorporating an HTML data attribute to every HTML element (div, section, etc) or image tag, telling RetinaJS to look for the high resolution variant of the defined image like so:

<img src="/images/my_image.png" data-rjs="2" />

This will then be re-rendered like so after the plugin is fired:

<img src="/images/my_image@2x.png" data-rjs="2" data-rjs-processed="true" width="200" height="120">

The height and width attributes were defined to restrict the image from growing and the source was swapped out. An added benefit is this technique will also work for an HTML element that has a background image:

<div style="background-image: url(/images/my_image.png)" data-rjs="2"></div>

This will then be re-rendered like so after the plugin is fired:

<div style="background-image: url(/images/my_image@2x.png); background-size: 200px 100px" data-rjs="2" data-rjs-processed="true"></div>

Experiencing the results for yourself

While I can stand on my soap box and preach the benefits of utilizing a method such as this, realistically the only way you can see the benefit is to actually "see" it.

I was recently part of a team that launched a completely redesigned website that utilizes the process outlined above. I can honestly say that the increased fidelity and quality of the product images within the site is absolutely stunning. And again, it is something that I cannot explain, you have to visually see it for yourself.

Hope this helps you make a decision on whether to include something like this website. I have had phenomenal success personally and I cannot say enough on the improved user experience it provides to a website.

Show Comments