Lazy and conditional image loading is a pretty common design pattern and more or less a necessity for larger responsive sites. The most common implementations swap a placeholder for the loaded image, either by using an element as a placeholder, E.G. <div data-image="*">
or an image tag with a temporary source. The problem is that neither of these are particularly well suited to a flexible layout, both techniques will also require a costly reflow on image load without fixed dimensions.
Using a little basic CSS, JavaScript and a dash of animation it’s simple to avoid the performance hit of re-calculating layout and provide a smooth user experience.
The markup
This technique requires a wrapper as well as a placeholder. The inner width of the wrapping block will be used to calculate the right size space in the layout. Attributes to be transferred to the eventual image element are specified as data attributes on the placeholder element.
The CSS
CSS margin and padding percentage values are calculated based on the width of the containing block and this effect is used to create space in the layout. My code relies on knowing the aspect ratio of the target image which I think is fine in the majority of cases, but it could also be calculated on the server for each image and output as an inline style of the placeholder element.
The JavaScript
No monolithic library is required, the core of this technique is just plain old (in both senses) JS. In future it could be updated to use the ES5 array .forEach()
method, classList
and dataset
APIs but they offer no immediately useful benefits here other than providing nice, terse syntax. The script adds classes to imply state and act as hooks for styling. Importantly, the onload
event listener is applied before the src
attribute to avoid it not being triggered in legacy Internet Explorer in the case that an image is loaded from the cache.
The animation
No one wants to see preloaders on the web now but it’s preferable to infer something is loading than to leave a rectangular gap, especially on flaky connections where multiple requests can cause issues. There’s no loading .gif files here though, instead leveraging pseudo-elements and keyframe animations to create a little loading bobble that will be smooth and resolution independent.
Conditionally loading images is a key performance technique, whether it’s for loading images of a different resolution or deciding if a browser cuts the mustard. The extra performance of minimising layout re-calculation can make an appreciable difference.