To bring you a fast-loading and photo-based home page, I’ve custom-made a responsive image system I call “ideal images.”
Whereas most sites serve one image to fit all screens, PhotoSecrets serves the optimum image for each screen. This minimizes bandwidth and load time, and gets full-resolution images to high-resolution devices.
For each image and aspect ratio, up to 50 file sizes are available, ranging from 60px to 2560px wide. Now, each device gets fast-loading AND full resolution images.
The HTML code for each ideal image looks like this:
class="img w50vw a1x1"
This decodes as:
|max:||2560 pixels wide|
As you can see, this is not an <img> element, so no image file is loaded initially. The CSS draws a box according to the class — in this case at 50% of the viewport width, and as a square (aspect 1x1).
The CSS would be:
padding:0 0 50vw 0;
For example, if the rendered size is 720 pixels wide, the image file will be:
The conundrum of responsive images
Serving appropriately sized images requires a technique known as “responsive images.” Although simple in theory, it is a conundrum in practice.
, yet there is no direct way for a device to request a specific image size.
For each image on a HTML page, we know the relative size but not the rendered size. For example, a full-width image will be rendered at 320 pixels wide on an iPhone 3, and 1125 pixels wide on an iPhone X. In my tests with optimized and compressed images, a 320-pixel-wide square image is 21 KB in size, and a 1125-pixel-wide image is 205 KB. That’s ten times as large.
|Notes: Width=CSS width (or points)|
Serving the large file to the small screen creates many problems:
- 90% of the data is wasted
- the transfer time is ten times longer than it should be
- the user pays ten times more for bandwidth
- the page render time is ten times longer
- the display memory is unnecessarily bloated and slower
Conversely, serving the small file to the large screen gives the user an image that is 1/10 the resolution it should be.
To serve fast websites with high quality images, some intelligence is required. There are several approaches available, but they all have drawbacks. Let’s take a look.
In HTML5, an <img> (image) tag can include the attribute srcset. This is a list of one or more strings separated by commas indicating a set of possible image sources for the user agent to use. The accompanying <sizes> tag can use media queries.
srcset="clock-img-200.png 200w, clock-img-400.png 400w"
sizes="(min-width: 600px) 200px, 50vw">
Although this is generally what I wanted, I calculated that around 50 images sizes are required to cater for most devices. With one <srcset> and one <sizes> attribute per image, that is 100 lines of code — per image. That would result in bloated and ugly HTML code.
A similar approach uses the HTML <picture> tag, which is a container used to specify multiple <source> elements for a specific <img> contained in it. The <source> element can use media queries.
However, this still still has the bloat problem above, and the <picture> tag is experimental technology.
The above approach can be hidden inside the CSS by using the background property and media queries. However, the bloat problem still exists, and if this is a separate CSS file, the image file info is removed from the HTML, which impairs the code readability.
An extension of the CSS background property is the image-set() function. However, this only addresses pixel density and is an experimental technology.
The server could detect the device type based on the HTTP_USER_AGENT string in the Apache .htaccess file, then serve the appropriate file size. However, this is straying too far from the HTML code for my liking.
A highly compressed high resolution image (HiDPI) can be sent, but this still provides high file size and imperfect images.
JPEG 2000 can store multiple sizes. In theory, the HTTP connection could be terminated when the appropriate size is received. However, site loading is faster when the connection is kept alive, so the browser ends up downloading a large file when only a small one may be needed. And JPEG 2000 is an experimental technology with little support.
Progressive JPEGs use interlaced display, like GIFs, to paint higher resolutions, but doesn’t address the rendered size problem.
This is the approach I took, where code analyzes the rendered size and downloads the optimum image.
— Pete LePage, Google Developer Advocate
Adaptive Images detects your visitor’s screen size and automatically creates, caches, and delivers device appropriate re-scaled versions of your web page’s embeded HTML images. No mark-up changes needed.”
Here are interesting links if you’re looking into this:
- Images in Responsive Web Design, by Pete LePage on Google Developers
- Responsive images in CSS, by Chris Coyier, CSS Tricks
- High DPI Images for Variable Pixel Densities, by Boris Smus, HTML5 Rocks
- Retina graphics by George Morris, an open source script that makes it easy to serve high-resolution images to devices with retina displays
- Responsive images done right, by Eric Portis, Smashing Magazine
- Responsive Images in Practice, also by Eric Portis, A List Apart
- CSS3 media queries
- CSS4 image set
- , by Craig Russell
- by Matt Wilcox