CraftCMS Template Based Image Transform for all the Sizes

Rich Bachman
Mar 15, 2018 · 2 min read
Image for post
Image for post

I’ve been diving into Craft more and more lately, and love the way it handles template driven image transforms.

Quick background note: image transforms save everyone from uploading images at certain sizes. Craft lets you define rules that tranform images in a non-destructive way. So say you need a thumbnail that is 200px by 200px, you can set up an image transform that will create a cropped thumbnail from the original image without destroying that original image.

Craft has a great UI for creating image transforms in the admin, and they also allow these transforms to be created directly in the template file.

This allows developers to easily set an image transform that creates all image sizes needed for 2x and 3x capable devices. The major plus goes to the client as they only need to upload one 3x size image, and Craft handles the rest.

One way I like to handle this uses the picture element, like so:

<picture>
// set the image variable and get the image
{% set ImageVar = entry.photo.first() %}
// get the width of the image and divide it by 3
{% set baseWidth = ImageVar.getWidth() / 3 %}
// get the height of the image and divide it by 3
{% set baseHeight = ImageVar.getHeight() / 3 %}
// use the divided widths and heights to output the image
<img
srcset="
{{ ImageVar.getUrl({ width: baseWidth, height: baseHeight }) }} 1x,
{{ ImageVar.getUrl({ width: baseWidth*2, height: baseHeight*2 }) }} 2x,
{{ ImageVar.getUrl({ width: baseWidth*3, height: baseHeight*3 }) }} 3x"
src="
{{ ImageVar.getUrl({ width: baseWidth, height: baseHeight }) }}
"
alt="{{ ImageVar.title }}"
>
</picture>

Basically, all we’re doing is getting the image width and height, dividing it and then multiplying it again for the image output. So the client only has to upload one 3x size image and their job is done.

I’ve found this method to work well for me, but any feedback or suggestions are appreciated.

UPDATE - 3/21/17

I received some great feedback from Tim Knight. He was gracious enough to improve on my initial idea and share some code samples.

In an effort to make the code a little more readable, you could put all the image details in a single array:

{% set baseWidth = image.getWidth() / 3 %}
{% set baseHeight = image.getHeight() / 3 %}
{% set images = {
base: {
width: baseWidth,
height: baseHeight,
},
double: {
width: baseWidth * 2,
height: baseHeight * 2,
},
triple: {
width: baseWidth * 3,
height: baseHeight * 3,
}
} %}
<picture>
<img
srcset="
{{ image.getUrl(images.base) }} 1x,
{{ image.getUrl(images.double) }} 2x,
{{ image.getUrl(images.triple) }} 3x"
src="{{ image.getUrl(images.base) }}"
alt="{{ image.title }}"
>
</picture>

Again, thank you to Tim Knight for sharing this idea, and helping to make Medium a collaborative space.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store