Hi! I'm Johannes Dachsel, a web designer and developer based near Heidelberg, Germany. This is my personal website. Get in touch

Johannes Dachsel

Using the <picture> element in Processwire: revisited

After introducing the notes section on this website, I needed a way to easily render images with picture element markup. So I wrote module for that.

Some time ago I wrote a Textformatter module for Processwire which scanned the content of a textarea for <img> elements and converted them into their previously configured <picture> equivalents.

This worked well until I introduced the notes section on this website. A note may very well contain an image but unlike the images in regular articles the images in notes are not rendered per textarea field. The note template uses Processwire’s Pageimage methods to put out the URL of the image directly into the template hence the Textformatter module I had written wouldn’t apply.

Enter: ImageToPicture module

So once again I wrote a module to solve the issue. After installing it, the module adds a new method to the Pageimage class which allows rendering any image with proper <picture> element markup.

The new toPicture() method can be called like this:

$image->toPicture();

There are some options available, to define queries and image sizes. These are the defaults:

$image->toPicture(array(
  'fallback' => 450, // width for fallback image
  'altText' => '', // alternative text (default is image description)
  'sources' => array(
    '(min-width: 64em)' => 600, // queries and image widths
    '(min-width: 45em)' => 520 
  )
));

Using toPicture() without any options renders the following output:

<picture>
  <source media="(min-width: 64em)" srcset="img-600px.jpg">
  <source media="(min-width: 45em)" srcset="img-520px.jpg">
  <img src="img-450px.jpg" alt="Image description">
</picture>

A customised call might look like this:

$image->toPicture(array(
  'fallback' => 300,
  'altText' => 'My new description',
  'sources' => array(
    '(min-width: 55em)' => 860,
    '(min-width: 27em)' => 450 
  )
));

Which produces:

<picture>
  <source media="(min-width: 55em)" srcset="img-860px.jpg">
  <source media="(min-width: 27em)" srcset="img-450px.jpg">
  <img src="img-300px.jpg" alt="My new description">
</picture>

The code is available on Github – perhaps it might be useful to somebody.