Earlier this year i wrote about a solution for optimizing the images on your Episerver site. Since then, that solution has been included in the ImageProcessor.Web.Episerver nuget package. With the Picture html helper included in the nuget it’s easy to optimize the images in size, quality, and file size. Images will be responsive, and can be lazy loaded.
The Picture helper renders a picture element. The picture element presents a smorgasbord of images in different sizes and formats. It’s then up to the browser to select the most appropriate image depending on screen resolution, viewport width, network speed, and the rules that you set up.
Update: Similar functionality for Optimizely CMS 12 is now available
This article shows the steps needed to start using the Picture helper, and also describe some of the details a bit more:
- Install the nugets
- Identify, and define the “image types” on your site
- Use the Picture html helper
- Tweak configuration (optional)
- Add lazy-load javascript (optional)
Install the nugets
ImageProcessor.Web.Episerver, or ImageProcessor.Web.Episerver.Azure if your site is hosted on Azure.
Define your image types
This is the only part that might might mean some work for you.
An image type contains the specifications for an image on a specific place on your site. Examples of image types: “Top hero image”, “Teaser image”, “Image gallery thumbnail”.
Image types are instances of the class ImageProcessor.Web.Episerver.ImageType. You set the following properties:
- SrcSetWidths, int[] – The different image widths you want the browser to select from. These values are used when rendering the srcset attribute.
- DefaultImgWidth, int – This image width will be used in browsers that don’t support the picture element. Used when rendering the img element.
- SrcSetSizes, string[] – Allows us to define the size the image should be according to a set of “media conditions” (similar to css media queries). Values are used to render the sizes attribute.
- HeightRatio (optional) – The aspect ratio for your image.
- Quality (optional) – Default value is 80
Image type samples
Use the Picture helper
In your Razor (.cshtml) view, you use the Picture helper like this:
@Html.Picture(Url.ContentUrl(Model.Image), ImageTypes.Teaser)
The rendered markup will be:
<picture> <source sizes="(max-width: 980px) calc((100vw - 40px)), (max-width: 1200px) 368px, 750px" srcset="/globalassets/alloy-plan/alloyplan.png?width=375 375w, /globalassets/alloy-plan/alloyplan.png?width=750 750w, /globalassets/alloy-plan/alloyplan.png?width=980 980w, /globalassets/alloy-plan/alloyplan.png?&width=1500 1500w"> <img alt="" src="/globalassets/alloy-plan/alloyplan.png?width=750"> </picture>
For jpeg images the Picture helper also creates webp versions. The webp version will be shown in browsers that support it, other browsers will fallback to jpeg.
Tweak the configuration
To make it easier to test that everything works as expected, you can add the appsetting “IPE_ShowInfo” in web.config. When that value is “true”, info about the images is shown on the image. To be able to show that info on the image you need to enable the “watermark” plugin for ImageProcessor. That is done in the file /config/imageprocessor processing.config
<plugin name="Watermark" type="ImageProcessor.Web.Processors.Watermark, ImageProcessor.Web" enabled="true" />
I also recommend increasing the time that the images are cached by browsers. That is done by increasing the “browserMaxDays” value in the file /config/imageprocessor cache.config
Add lazy-loading of images
The Picture helper can render the picture element in a way that makes it possible to lazy-load the image. The srcset (and src, for the img element) attributes will be empty and instead another attribute, named data-srcset (and data-src), will contain the different urls to the image. When your page has finished loading you use javascript to copy the urls to the srcset attribute. How you implement that javascript is up to you, but here is an example that uses IntersectionObserver to make the images load when the user scrolls down on a page.
Update: See also the option for native lazy loading that was added in v5.6
The lazyLoadType parameter is what makes this all happen:
@Html.Picture(Url.ContentUrl(Model.Image), ImageTypes.Teaser, LazyLoadType.Progressive)
When lazy load type is set to “CustomProgressive”, the srcset attribute will contain image url(s) for a low quality version of the image, and the data-srcset will contain urls for the high quality version. That means that when the page loads, a low quality version will be visible, and then the high quality version will be loaded using javascript. That can be useful for example for images at the top of your page that you want to be visible immediately, but at the same time you don’t want the loading of a large high-quality image to block the loading of the rest of the page.
Will this impact server performance?
I haven’t done any extensive performance testing. But the tests I’ve done, doesn’t show any impact on server performance at all, when using ImageProcessor + Picture helper.
Other links that might be of interest
- Control how Picture helper will crop your images.
- Original articles about the Picture helper are found here and here
- More info about responsive images and picture element here, here, here, and here.
At time of writing I was using Episerver 11.10.4 and ImageProcessor.Web.Episerver 4.2.0. Later updated to use the “IPE_ShowInfo” appsetting introduced in ImageProcessor.Web.Episerver 5.1, and native lay loading included in 5.6
This is great! I had to recently implement image compression using the ImageResizer nuget with the tag and all the srcset tags inside, written line by line in the HTML, but I like that you implemented a helper so it’s shorter and the HTML is much cleaner. I have yet to try the lazy-loading. Thanks for sharing!
I can’t get the debug info to work. I’ve added the ImageProcessorDebug appsetting and enabled the Watermark plugin. I’m running ImageProcessor.Web.Episerver version 5.3.0.26423.
Since v5.1 the appsetting is called “IPE_ShowInfo”. I will update the text shortly. Please also take a look at the github repo, for the latest documentation.
Hope that helps!
Great, thanks!
No credit to James Jackson-South? ImageProcessor is open source and is the result of thousands of hours by him