One of the greatest challenges that come with creating a responsive, mobile-friendly site is to adapt your images for various smaller resolutions so that they're not the bandwidth-eating monsters you normally get on a desktop resolution. Who wants a slider with ten 1920x600px banners on a 480px wide screen, especially when your mobile device is not connected to Wi-Fi and is consuming data from your mobile data package?
The problem is that estimating the viewport size on the server side is not always accurate and can sometimes lead to wrong image dimensions, damaging the overall layout of your site. You can, of course, use CSS with media queries to define different images for different viewports on the client side, but my guess is that if you're reading this you already have tried or you don't want to. And you're right. It's a very boring and "static" process, and to make it dynamic like the rest of the Umbraco stuff you'll have to use tons of inline CSS - not very good for performance.
The SRCSET attribute
Enter srcset - a HTML 5 attribute that delegates image selection to the browser. You just hint what image goes with what viewport size and let the browser decide what to load.
If you haven't heard about srcset yet, here's an excellent article that explains it better than I ever could: https://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/
Umbraco already features the Image Cropper data type which uses Image Processor (http://imageprocessor.org/imageprocessor-web/) behind the scenes, so Umbraco can take an image a user uploads and resize it or crop it, in real time, to given dimensions (and then cache it so that it doesn't have to do that again)
Using SRCSET together with the Image Cropper
So, what can we do if we combine srcset with Image Cropper? We can have a function that automatically generates the srcset attribute data for a given image. See this example:
<img srcset="/media/1006/city.jpg?anchor=center&mode=crop&width=94&height=52&rnd=131471984450000000 94w,
This is an IMG tag with srcset attribute and a fallback src attribute at the end, while all image versions have been programmatically created with Image Cropper based on a single Media image (/media/1006/city.jpg). Browsers which support srcset will select the best image to download, for example, if the viewport is 600px or less it'll load the 600px width version of the image.
The srcset attribute is created automatically by a call like the following:
srcset="@myNode.Image.GetSrcSet(1280, 720, "94,300,600,768,1024,1280")"
src="@myNode.Image.GetCropUrl(width: 1280, height: 720, imageCropMode: ImageCropMode.Max, upScale: true)"
where "myNode" is an IPublishedContent object and "Image" is a strongly-typed Image Cropper property.
The GetSrcSet extension method
The GetSrcSet extension method does all the work of calculating stuff and providing the srcset data. The GetSrcSet accepts three optional arguments: width and height of original crop, and a comma delimited string of max viewport widths.
The height and width arguments are used if you need to actually crop the image (and, subsequently, change its original aspect ratio). GetSrcSet will calculate all other images' crops based on the new aspect ratio. Or, you can just not define width and height at all to go with the original image's aspect ratio (without cropping anything). Another way is to only define the width attribute, which will serve as the max width for the image, in case the image uploaded is huge.
Also, the comma delimited list of viewport widths can also be omitted since there's a default value in place. You can use it when you need different specific values, though.
The "src" argument is provided via the classic GetCropUrl extension method and serves as a fallback in case the browser doesn't support the srcset attribute. It's good practice to have the maximum expected image size there, just in case. The browser will NOT load this image at all if it supports srcset.
Here's the code for the extension method. Current namespace is DotSee.Common but you can change it to whatever suits you.
Some additional notes:
Browser compatibility - If you're worried that srcset is not supported by all browsers, you're - partially - right. Older browser versions do not support it. But they'll always fall back to the original src attribute, so worst case scenario is that they'll be loading huge images in mobile resolutions - which is incentive enough for users to upgrade :) Here's a compatibility chart: https://caniuse.com/#feat=srcset
Verifying that the browser is choosing the correct image - Please note that the browser will prefer images that are in your computer's local cache to those it has to get from the Internet. So, if you already have loaded a page containing some images once, and then switch your browser to a smaller resolution, it'll still load the larger images. You can avoid that in Chrome by enabling Chrome's Debug mode, which has an option to disable caching. (And probably, with a similar method, in other browsers too).