PageimageSource by NB Communication

Extends Pageimage with a srcset property/method plus additional rendering options.

PageimageSource

Extends Pageimage with a srcset property/method plus additional rendering options.

Overview


The main purpose of this module is to make srcset implementation as simple as possible in your template code.

For an introduction to srcset, please read this Mozilla article about responsive images.

Installation


  1. Download the zip file at Github or clone the repo into your site/modules directory.
  2. If you downloaded the zip file, extract it in your sites/modules directory.
  3. In your admin, go to Modules > Refresh, then Modules > New, then click on the Install button for this module.

ProcessWire >= 3.0.165 and PHP >= 7.3 are required to use this module.

Configuration


To configure this module, go to Modules > Configure > PageimageSource.

Default Set Rules

These are the default set rules that will be used when none are specified, e.g. when calling the property: $image->srcset.

Each set rule should be entered on a new line, in the format {width}x{height} {inherentwidth}w|{resolution}x.

Not all arguments are required - you will probably find that specifying the width is sufficient for most cases. Here's a few examples of valid set rules and the srcsets they generate:

Set RuleSrcset GeneratedArguments Used
320image.320x0-srcset.jpg 320w{width}
480x540image.480x540-srcset.jpg 480w{width}x{height}
640x480 768wimage.640x480-srcset.jpg 768w{width}x{height} {inherentwidth}w
2048 2ximage.2048x0-srcset.jpg 2x{width} {resolution}x

How you configure your rules is dependent on the needs of the site you are developing; there are no prescriptive rules that will meet the needs of most situations. This article gives a good overview of some of the things to consider.

When you save your rules, a preview of the srcset generated and an equivalent method call will be displayed to the right. Invalid rules will not be used, and you will be notified of this.

Use for all dimensions?

If enabled, a set rule will be used regardless of whether it is wider or higher than the dimensions of the original image.

To use this on a srcset call, enable the allSets option:

$srcset = $image->srcset('4096, 2048, 1024, 512, 256', [
	'allSets' => true,
]);
// If passing an image 2000px in width, the above would return a srcset with set rules for each given width
// Without 'allSets' enabled, the srcset generation would terminate at 4096w
// Equivalent render()
$rendered = $image->render([
	'srcset' => [
		'rules' => '4096, 2048, 1024, 512, 256',
		'options' => [
			'allSets' => true,
		],
 	],
]);

WebP

If enabled, WebP versions of the image and srcset variations will be generated and these will be returned by Pageimage::srcset(). As with the default implementation, the image with the smaller file size is returned. In most cases this is the WebP version, but sometimes can be the source.

Make sure to experiment with the quality setting to find a value you find suitable. The default value of 90 is fine, but it is possible that lower values will give you excellent kB savings with little change in overall quality.

For more information on WebP implementation please read the blog posts on the ProcessWire website.

Rendering

These settings control how the output of Pageimage::render() is modified.

Use Lazy Loading?

When enabled this adds loading="lazy" to the <img> attributes. It is useful to have this on by default, and you can always override it in the options for a specific image.

Use the <picture> element?

When enabled, the <img> element is wrapped in a <picture> element and <source> elements for original and WebP variations are provided. This requires WebP to be enabled. For more information on what this does, have a look at the examples in Pageimage::render() below.

Remove Variations

If checked, the image variations generated by this module are cleared on Submit. On large sites, this may take a while. It makes sense to run this after you have made changes to the set rules.

Please note that although the module will generate WebP versions of all images if enabled, it will only remove the variations with the 'srcset' suffix.

Usage


Pageimage::srcset()

// The property, which uses the set rules in the module configuration
$srcset = $image->srcset;

// A method call, using a set rules string
// Delimiting with a newline (\n) would also work, but not as readable
$srcset = $image->srcset('320, 480, 640x480 768w, 1240, 2048 2x');

// The same as above but using an indexed/sequential array
$srcset = $image->srcset([
	'320',
	'480',
	'640x480 768w',
	'1240',
	'2048 2x',
]);

// The same as above but using an associative array
// No rule checking is performed
$srcset = $image->srcset([
	'320w' => [320],
	'480w' => [480],
	'768w' => [640, 480],
	'1240w' => [1240],
	'2x' => [2048],
]);

// The set rules above are a demonstration, not a recommendation!

Image variations are only created for set rules which require a smaller image than the Pageimage itself. This may still result in a lot of images being generated. If you have limited storage, please use this module wisely.

Pageimage::render()

This module extends the options available to this method with:

  • srcset: When the module is installed, this will always be added, unless set to false. Any values in the formats described above can be passed.
  • sizes: If no sizes are specified, a default of 100vw is assumed.
  • lazy: Pass true to add loading=lazy, otherwise false to disable if enabled in the module configuration.
  • picture: Pass true to use the <picture> element, otherwise false to disable if enabled in the module configuration. Alternatively, you can pass a <picture> tag with any additional attributes you wish to use.

Please refer to the API Reference for more information about this method.

// Render an image using the default set rules
// WebP and lazy loading are enabled, and example output is given for <picture> disabled and enabled
echo $image->render();
// <img src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.webp' alt='' srcset='image.jpg...' sizes='100vw' loading='lazy'>
/*
<picture>
	<source srcset="image.webp..." sizes="100vw" type="image/webp">
	<source srcset="image.jpg..." sizes="100vw" type="image/jpeg">
	<img src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.jpg" alt="" loading="lazy">
</picture>
*/

// Render an image using custom set rules
echo $image->render(['srcset' => '480, 1240x640']);
// <img src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.webp' alt='' srcset='image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w' sizes='100vw' loading='lazy'>
/*
<picture>
	<source srcset="image.480x0-srcset.webp 480w, image.1240x640-srcset.webp 1240w" sizes="100vw" type="image/webp">
	<source srcset="image.480x0-srcset.jpg 480w, image.1240x640-srcset.jpg 1240w" sizes="100vw" type="image/jpeg">
	<img src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.jpg" alt="" loading="lazy">
</picture>
*/

// Please note, if upscaling is off and your original image is smaller than a set rule, it will not be used exactly.
// For example, an image 1080px wide would generate 'image.1080x640-srcset.ext' above.
// Turn on upscaling
$image->render([
	'srcset' => [
		'rules' => '480, 1240x640',
		'options' => [
			'upscaling' => true,
		],
	],
]);

// Render an image using custom set rules and sizes
// Also use the `markup` argument
// Also disable lazy loading
// In this example the original jpg is smaller than the webp version
echo $image->render('<img class="image" src="{url}" alt="Image">', [
	'srcset' => '480, 1240',
	'sizes' => '(min-width: 1240px) 50vw',
	'lazy' => false,
]);
// <img class='image' src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.jpg' alt='Image' srcset='image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w' sizes='(min-width: 1240px) 50vw'>
/*
<picture>
	<source srcset="image.480x0-srcset.webp 480w, image.1240x0-srcset.webp 1240w" sizes="(min-width: 1240px) 50vw" type="image/webp">
	<source srcset="image.480x0-srcset.jpg 480w, image.1240x0-srcset.jpg 1240w" sizes="(min-width: 1240px) 50vw" type="image/jpeg">
	<img class='image' src="https://raw.githubusercontent.com/nbcommunication/PageimageSource/main/image.jpg' alt='Image'>
</picture>
*/

// Render an image using custom set rules and sizes
// These rules will render 'portrait' versions of the image for tablet and mobile
// Note the advanced use of the `srcset` option passing both `rules` and image `options`
// WebP is disabled
// Picture is disabled
echo $image->render([
	'srcset' => [
		'rules' => '320x569, 640x1138, 768x1365, 1024, 1366, 1600, 1920',
		'options' => [
			'upscaling' => true,
			'hidpi' => true,
		],
	],
	'sizes' => '(orientation: portrait) and (max-width: 640px) 50vw',
	'picture' => false,
]);
// <img src='image.jpg' alt='' srcset='image.320x569-srcset-hidpi.jpg 320w, image.640x1138-srcset-hidpi.jpg 640w, image.768x1365-srcset-hidpi.jpg 768w, image.1024x0-srcset-hidpi.jpg 1024w, image.1366x0-srcset-hidpi.jpg 1366w, image.1600x0-srcset-hidpi.jpg 1600w, image.jpg 1920w' sizes='(orientation: portrait) and (max-width: 768px) 50vw' loading="lazy">

TextformatterPageimageSource


Bundled with this module is a Textformatter largely based on TextformatterWebpImages by Ryan Cramer. When applied to a field, it searches for <img> elements and replaces them with the default output of Pageimage::render() for each image/image variation.

Assuming a default set of 480, 960 and lazy loading enabled, here are some examples of what would be returned:

Example

<figure class="align_right hidpi">
	<a href="/site/assets/files/1/example.jpg">
		<img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" />
	</a>
</figure>

WebP enabled

<figure class="align_right hidpi">
	<a href="/site/assets/files/1/example.jpg">
		<img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.webp" width="300" srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" loading="lazy" />
	</a>
</figure>

<picture> enabled

<figure class="align_right hidpi">
	<a href="/site/assets/files/1/example.jpg">
		<picture>
			<source srcset="/site/assets/files/1/example.300x0-is-hidpi.webp 480w" sizes="100vw" type="image/webp">
			<source srcset="/site/assets/files/1/example.300x0-is-hidpi.jpg 480w" sizes="100vw" type="image/jpeg">
			<img alt="" src="/site/assets/files/1/example.300x0-is-hidpi.jpg" width="300" loading="lazy" />
		</picture>
	</a>
</figure>

Because the variation is small - 300px wide - the srcset only returns the source image variation at the lowest set width (480w). If the source image was > 1000px wide, there would be a variation at both 480w and 960w.

PageimageSrcset


This module is built upon work done for PageimageSrcset, which can be considered a first iteration of this module, and is now deprecated.

Migration

PageimageSource is a simplified version of PageimageSrcset with a different approach to rendering. Most of the features of the old module have been removed. If you were just using $image->srcset(), migration should be possible, as this functionality is essentially the same albeit with some improvements to image variation generation.

License


This project is licensed under the Mozilla Public License Version 2.0.

Install and use modules at your own risk. Always have a site and database backup before installing new modules.

Latest news

  • ProcessWire Weekly #554
    In the 554th issue of ProcessWire Weekly we'll check out the latest core updates, introduce a couple of new third party modules, and more. Read on!
    Weekly.pw / 21 December 2024
  • Custom Fields Module
    This week we look at a new ProFields module named Custom Fields. This module provides a way to rapidly build out ProcessWire fields that contain any number of subfields/properties within them.
    Blog / 30 August 2024
  • Subscribe to weekly ProcessWire news

“We were really happy to build our new portfolio website on ProcessWire! We wanted something that gave us plenty of control on the back-end, without any bloat on the front end - just a nice, easy to access API for all our content that left us free to design and build however we liked.” —Castus, web design agency in Sheffield, UK