Retina and Responsive HTML5 Images
With the popularity of retina and high definition displays on the rise it is now more important than ever for web developers to use high definition images. There are a couple of ways to tackle this. I am going to cover the following methods:
- Load 2x images everywhere and set the image height and width to the 1x size
- Use the srcset HTML5 attribute
- Using the picture HTML5 element
Load 2x Everywhere
This is probably the easiest solution, but not good for your mobile and non-retina users as you will be loading high definition images for all users. Non-retina users on a broadband connection will likely not notice it, however, your mobile users or those with a slower connection are likely to wait longer for your page to load.
- Specify the img src to use the high definition graphic
- Specify the height and width of the image to the non-retina size
For example, the non-retina (or high definition, I will probably interchange these terms) image is 100×200 pixels. So, specify the height and width of the image using CSS or the attributes in your HTML to be 100×200. But, load the image that is twice the size, or 200×400 pixels.
Your HTML for this might look like:
<img src="/firstname.lastname@example.org" style="height:100px; width: 200px;" alt="bar" />
Briefly, the most common approach is to loop over all of the images in the DOM and to attempt to load the high definition image. Retinajs looks for images on your server that match the file name plus @2x appended. This naming convention is becoming standard after being created by Apple for iOS. If the image file exists on your server (returns a 200 status code), then the retina image is substituted for the non-retina one. Of course, it also has to enforce the original image dimensions (just like what we did previously with loading retina images everywhere) so that the images do not appear twice the size on the screen.
This solution works well, but there are several downsides:
- The browser still loads the non-retina image first, which is unnecessary for retina users.
- Retina users may notice the fuzzy images first before they are replaced with the high definition retina graphics. There is not really a “flash**, but it can be noticeable.
HTML5 srcset Attribute
srcset attribute for the
<img> element has been proposed by the W3C as part of the HTML5 specification and it has already been implemented in some of the browsers.
The first two methods that I wrote about above are really just hacks until we have broad support for high definition images in the browsers.
They are both adequate solutions but we can clearly see the need for a standard approach that is implemented by the major browsers.
Enter the next two methods: using the
srcset attribute and using the new
srcset attribute enables you to specify a list of image sources to use based on the width of the browser and the pixel density of the device.
This is really cool, and I'm very happy to say that Google Chrome has already implemented this.
You can see what browsers have implemented this at caniuse.com/srcset.
Note that WebKit (the rendering engine for Safari) has already implemented this and it will likely be released in Safari 8 that will ship with OS X.
The HTML syntax for loading the retina display might look like:
<img src="/images/foo.png" alt="bar" srcset="/images/foo.png 2x" />
Nice and clean.
You can also specify a list for the
Using a list for
srcset enables the developer to tell the browser that there are other image sizes available that can be used in place of the default src image.
wflag we can tell the browser that we have the same image available in different widths.
The width is similar to using the
max-width CSS property in media queries.
For example, we can enable the browser to use a medium and large image based on the sizes of the image in the viewport:
<img src="/images/foo.png" alt="bar" srcset=" /images/foo-medium.png 1024w, /images/foo-large.png 2048w, /images/foo.png 800w " />
Combining this with the
sizes attribute, the browser can choose the image that is best suited for the user based on the desired size of the image in the viewport and the available image sizes provided in the
With the sizes attribute we can also use media queries to set the size relative to the viewport based on the width of the viewport.
Here is an example of showing the image at 50% of the viewport width on desktops and 100% on mobile devices.
<img src="/images/foo.png" alt="bar" srcset="/images/foo-medium.png 1024w, /images/foo.png 800w" sizes="(min-width: 1024px) 1024px, 800px" />
srcset attribute is a great way to include high definition graphics for your retina display users.
Further, the browser will not load the standard low definition image for retina display users, so there is no hit on the page load weight.
And combining the
sizes attributes you can further specify the width of your image in the browser's viewport so that the browser can choose the best fit image to display to your user.
HTML5 picture Element
The last method that I will talk about is the new
The picture element will use a similar approach as the HTML5
<video> elements allowing you to specify multiple sources with the option to fallback to the default non-retina image.
The picture element uses the
sizes attributes that we discussed above, and encapsulates the various image sources that the browser can choose from based on the width of the viewport and the devices pixel density.
Unfortunately, at the time of this writing it is not yet implemented in any of the major browsers: caniuse.com/picture.
In the following example we are going to specify two different
sources for the picture with a fallback to the original image.
<source> uses a media query to limit the source to be used only on devices that have a screen resolution greater than 1024 pixels.
<source> also specifies various image sizes to be used based on the width of the viewport.
<source> specifies the images to be used based on the pixel density of the device.
<img> tag uses the default image to display in the browser.
<img> tag is always required when using the
The first two
sources will not display an image in the browser if the
img tag is missing.
sources simply provide information to the browser so that it can choose the best image to display based on the viewport size and the pixel density of the device.
<picture> <source media='"(min-width:' 1024px)" srcset='"foo-large.jpg' 1024w, foo-medium.jpg 640w, foo-small.jpg 320w" sizes='"50vw"' /> <source srcset='"email@example.com' 2x, foo.jpg 1x" /> <img src='"foo.jpg"' alt='"Bar"' /> </picture>
I hope this post has helped you to learn more about retina and responsive images in HTML5. The future of high definition devices and images is now. There is no reason to not begin adding retina and responsive images to your website today.