Responsive images: a lazy alternative take, embracing microdata

Hang on, we just got the picture element! Right?!?

You might have immediately thought about the picture element which finally makes its way into the most current browsers with polyfills available for older browsers. Case closed!

If things were that dead simple I would certainly not write an article about it. In fact I have been keeping an eye on the picture element for a very long time and always hoped it would finally establish itself against srcset - which I personally never really liked for various reasons.

What we end up having now is, sadly enough, in my eyes an over-sufficient mess of both that lost its focus on real world application to some degree. Sure, mixing both opens seemlessly endless possibilities to alter the used image according to whatever obscure use case you might have to solve. But honestly, most of the time you will simply want to load the same image with its actual dimensions eventually adding the device pixel ratio into the mix.

Yes, you can do this with the picture element in its current form, although some polyfills lack support for certain features (the defined standard really is quite complex in regards to the order of rules I admit). But you will need tons of HTML to fullfill a quite simple requirement like the one shown above.

In addition, one thing the picture element does not cope with and which is one of the main things I expected it to be able to solve (or at least providing means to do so) is the possibility to lazy-load images. In this respect the picture element does not only not solve this problem, it simply fails. Reason: in the current definition a picture element MUST have at least one valid image element. This image element will at least get requested when using ANY kind of polyfill, which still applies to the majority of browsers nowadays. In my UX focused eyes wanting to optimize perceived loading time as much as possible this is an absolute no-go.

OK, so is there a different approach?

I am not only focused on UX and perceived loading time but also on semantic use of HTML in regards to accessibility and SEO and for that reason try to incorporate any means that improve a sites performance in any of these fields.

So I happened to come across microdata1 as supported by Google and other major search engines and studied its usage, use cases and examples. And what I found in the examples changed my world dramatically. Although having been in this business for a very very long time I had never even thought about using HTML meta tags somewhere outside of the document head. But doing this is perfectly valid and offers, combined with microdata semantics, a great way of writing SEO compatible content that does not get rendered in the browser immediately!

To give you an example of how I handle images on this particular site here is the HTML code for the visual on the homepage:

<figure itemscope data-ratio="0.57142857142857" itemtype="http://schema.org/ImageObject">
    <meta itemprop="contentUrl" content="portfolio/assets/0.0.5/images/works/eyelabel.vodafone.interim.jpg" />
    <meta itemprop="caption" content="Vodafone Institute interim website" />
</figure>

You see I am using a figure element here with an itemtype of ImageObject and two meta tags containing the contentUrl and caption of the image. This is perfectly valid HTML and microdata which, in addition, gets indexed by search engines.

What I do via JavaScript is to attach my Qoopido.js emerge module to all nodes with an attribute itemtype with the value http://schema.org/ImageObject and if any of these elements scrolls into view I calculate its size and get the device pixel ratio and only then request the image in its actual size to get displayed.

Attentive readers will now point out that the whole lazy-loading cannot work correctly because the figure element does not have an initial size which leads to it effectively having a height of 0px.

To solve this issue I added a data-ratio attribute to the figure element (which could also have been calculated via additional meta tags for the image's width and height) which adds image like behaviour to any element. Images do have the somewhat special behaviour to keep their aspect ratio when only width is set via CSS. This does perfectly solve the height issues described above :)

The final HTML code as altered via JavaScript will look like this:

<figure itemscope data-ratio="0.57142857142857" itemtype="http://schema.org/ImageObject" style="position: relative; display: block; width: 100%; height: 0px; padding-bottom: 57.142857142857%;">
    <meta itemprop="contentUrl" content="portfolio/assets/0.0.5/images/works/eyelabel.vodafone.interim.jpg" />
    <meta itemprop="caption" content="Vodafone Institute interim website" />
    <img src="portfolio/assets/0.0.5/images/works/eyelabel.vodafone.interim.840x480@2.jpg" alt="Vodafone Institute interim website" style="position: absolute; display: block; width: 100%; height: 100%; top: 0px; left: 0px; margin: 0px; padding: 0px;" />
</figure>

The initial idea is working so perfectly well that I incorporated it into my Qoopido.js2 library as a widget named adapt. In addition to the given example it is also capable of having multiple contenURLs that may have different data-ratio and also support data-media which may contain any type of standards conform media query. The first contentURL that matches will win over the following, so the whole thing is quite easy to understand and maintain.