28.11.2013

The Holy Grail of Adaptive Images

Internet is spreading rapidly over a large number of devices. Not only mobile phones or tablets but a growing number of other household appliances can be used to browse web pages. Bandwidths are growing too, but not as rapidly. That means the internet should adapt and the pages must be readable on biggest range of devices.
holy-grail

Responsive design is the answer for those needs. Layouts get simpler, unnecessary content doesn’t show and menus are touch-optimized. All of these are great and improve the user experience on handheld devices. But one of the most critical questions remains unanswered: how do we serve different sized images for different devices?

It is unnecessary and stupid to push 2000 pixels wide images to a phone that has horizontal resolution of 480 pixels. CSS media queries make it easy to serve different sized background-images based on viewport size or DPI.

Same methods don’t apply to ordinary images though. There have been plenty of propositions of how to handle the issue, but none of them have been impletented to work on any browsers. There is one solution though, that works already. The so-called Clown Car Technique utilizes SVG and it’s ability to contain both raster images and CSS media queries.

The original article about Clown Car Technique by Estelle Weyl can be found here. The basic idea is, that the SVG canvas is filled entirely with one element that has nothing else but a raster background-image.

That background-image can be defined using CSS, which means that we can use media queries to choose the right size image.

<svg xmlns="http://www.w3.org/2000/svg" 
   viewBox="0 0 300 329" preserveAspectRatio="xMidYMid meet">

<title>Clown Car Technique</title>

<style>
svg {
	background-size: 100% 100%;
	background-repeat: no-repeat;
}

@media screen and (max-width: 400px) {
	svg {
		background-image: url(images/small.png");
	}
}

@media screen and (min-width: 401px) and (max-width: 700px) {
	svg {
		background-image: url(images/medium.png);
	}
}

@media screen and (min-width: 701px) and (max-width: 1000px) {
	svg {
		background-image: url(images/big.png);
	}
}

@media screen and (min-width: 1001px) {
	svg {
		background-image: url(images/huge.png);
	}
}
</style>
</svg>

Like Estelle Weyl has noticed and published in her article, the usual <img> element does not work with SVG’s that use external images due to security reasons. That’s why we need to use <object> element. You can read more about the markup and attributes that can be used with <object> from the original article.

One big drawback with <object> and an SVG image is that Android browser and Windows version of Safari have a bug handling them. The height of the element is always 150 pixels.

We wrestled the issue for some time and finally came up with an answer. The <object> element should be wrapper with a <div> that has the right dimensions and defining the <object> itself width and height of 100%.

<div style="padding-top: 75%; position: relative;">
		<object data="images/fourbythree.svg" type="image/svg+xml" tab-index="0" role="img" style="width: 100%; height: 100; position: absolute; top: 0px; left: 0px;">
		  <!--[if lte IE 8]>
		      <img src="images/fourbythree_2.png" alt="Fallback for IE">
		  <![endif]-->
		</object> 
	</div>

The padding-top: 75%; forces the otherwise empty div to be exactly in 4:3 ratio. (3/4 is 0.75, see what I did there?) The result is not the prettiest in the world, but it works and there are lots customizing you could do with both the <object> and the surrounding <div>.

Obviously this technique requires lot of work to create the SVG, the corresponding <div> and <object> and the different sized images. It does, however, come with great profits. We changed the Geniem.fi frontpage to use this technique. While watching the page on a FullHD resolution monitor the browser downloads 6.2MB of data due to large images. When the horizontal resolution is 480 pixels, the amount of transfered data reduces to 1.9MB, under a third from original.

Fortunately for you, we have created a tool to help you to generate needed images and markup. Geniem Adaptive Image Generator wants the original image (JPG, PNG and GIF are all fine) and asks for you the breakpoints you want. It then returns a ZIP package containing resized and losslessly compressed images, SVG file and the HTML to insert into your web page. It won’t get much easier than this.