By using the picture element together with ImageProcessor, you can create a robust solution for responsive images. With this solution you can very quickly make sure that you at least don’t serve way too big images. Once that is done, you can add more image sizes and fine tune the media queries, to further optimize the images on your site.
UPDATE: The Picture Html helper described below is now included in the ImageProcessor.Web.Episerver nuget. Read more here.
ImageProcessor is a great, free, library for image manipulation. You can use it with any Asp.Net Framework site. It’s bundled with Umbraco, and lucky for us Vincent Baaij recently made it possible to use ImageProcessor together with Episerver.
When using the picture element you let the browser decide what image to use depending on viewport width, device pixel ratio and even network speed
You can read about the theory behind responsive images, and how to use the picture element, together with the “srcset” and “sizes” attributes here, here, and here.
My solution consists of two parts (I’m assuming ImageProcessor nugets are already added to your solution):
The image types
An image type is an image on a specific place on your site. Examples of image types: “Top hero image”, “Contact person image”, “Image gallery thumbnail”.
Instances of the ImageType class contains all the information needed to render the picture element for the specific image type. E.g. the different widths of the Top hero image at specific viewport widths
The “Picture” html helper
Takes care of the actual rendering of the picture-element and its sub-element. The html-helper takes an ImageType and an image-url as input parameters.
To make it easier to test that everything works as expected, I added the appsetting “ImageProcessorDebug” in web.config. When that value is true, the width of the image will be shown in the image (you need to enable “watermark” in processing.config for that to work).
How to use the Picture helper
If we want to use responsive images for the teasers on the Alloy site we would change this:
<div @html.editattributes(x=> x.Image)> <imgsrc="@Url.ContentUrl(Model.Image)" /></div>
<div @html.editattributes(x=> x.Image)> @Html.Picture(Url.ContentUrl(Model.Image), ImageTypes.Teaser)</div>
The resulting markup would be
<picture> <sourcesizes="(max-width: 980px) calc((100vw - 40px)), (max-width: 1200px) 298px, 368px, " srcset="/globalassets/alloy-plan/alloyplan.png?width=298 298w, /globalassets/alloy-plan/alloyplan.png?width=375 375w, /globalassets/alloy-plan/alloyplan.png?width=500 500w, /globalassets/alloy-plan/alloyplan.png?width=750 750w, /globalassets/alloy-plan/alloyplan.png?width=980 980w, /globalassets/alloy-plan/alloyplan.png?width=1024 1024w, /globalassets/alloy-plan/alloyplan.png?width=1400 1400w, /globalassets/alloy-plan/alloyplan.png?width=1500 1500w, "> <imgsrc="/globalassets/alloy-plan/alloyplan.png?width=750"> </picture>
Below you can see how different images are selected by Firefox when resizing the browser window.
When using a mobile with a higher device pixel ratio, a higher resolution image will be selected by the browser.
…and when you flip the phone, an even higher resolution image will be selected
Image type “Art direction”
This solution could be extended to support simple “art direction”. Maybe your full-width Hero image has lesser height on really wide screens? No problem, you could extend the image type to also specify the height of the image.
Happy coding! 🙂
At time of writing I was using Episerver 18.104.22.168
8 thoughts on “Picture element + ImageProcessor = responsive images made easy”
Just a small remark. Although I work for Episerver, I created the package on my own and it is not supported by Episerver.
I try to support it as good as possible myself through GitHub.
Thanks Vincent. I’ve updated the post.
Looks nice! Imageresizer also works as a charm:
Thanks! Yes, this solution will also work with ImageResizer without any changes. I’ve been using ImageResizer for years, but the new prices for ImageResizer are significant higher than before. The free version may be enough for the smallest sites, but in most cases you need the disk-cache plugin. Its good to have a free alternative.
nice! we were just chatting yesterday with colleague of mine about this 😉 and came to conclusions that IR plugin should have ready made helper 😉
does it make sense to make one there as well?! (have couple other ideas about consumer API surface compared to your elegant solution tho)..
If I used IR, I’d love to get that helper in the nuget. Maybe I should to a pull-request to the ImageProcessor plugin and see what Vincent thinks about it 🙂
Sounds like a plan!
then I’m waiting for PR?! 🙂