{{craftSnippets}}
Home Articles Plugins Starter theme Components on Github Gists About
  • Home
  • Articles
  • Placeholder image macro for Craft CMS
Posted on Mar 11, 2020 by Piotr Pogorzelski

Placeholder image macro for Craft CMS

Placeholder image macro on github gists

Notification

Since the time I wrote this article, I released Image Toolbox plugin which handles generating image placeholders and many other image-related functionalities.
I recommend using it instead of the method described here.

By using simple Twig macro, you can generate a placeholder image with specific dimensions.
Table of contents:
  • Placeholder images
  • SVG placeholder macro
  • Placeholder macro using external service

Placeholder images #

Sometimes website layout depends on images that have specific dimensions. If these images are missing or have wrong sizes - layout just looks wrong or even breaks. In such situations, it's pretty useful to have a placeholder image that takes place of missing images and has the same dimensions as the missing image.

SVG placeholder macro #

This macro will output transformed image, and if the image is missing it will output placeholder image. Placeholder will have the same width and height that image was supposed to have - assuming that width and height were set in transform settings. If only width or only height was set, placeholder will take the form of the square. And if width and height are missing - placeholder will not be outputted.

The generated placeholder image is not file that exists on the server - it is SVG with specific dimensions (and SVG is just a string) that is encoded to URL format and put into src of <img> tag. Such a placeholder image is transparent - so we may give it some background-image - for example, graphic like THIS. Or we can just give it some background color.

Here's macro code:

{%- macro transformOrPlaceholder(image, settings, attributes = {}) -%}
{# settings #}
{% set placeholderStyle = {
    'background-image': 'url(placeholder.jpg)',
    'background-position': 'center',
    'background-size': 'cover',
} %}
{# logic #}
{% if image is not null %}
{% set src = image.getUrl(settings) %}
{% set attributes = attributes|merge({src: src}) %}
{{tag('img', attributes)}}
{% elseif settings.width is defined or settings.height is defined %}
{% set width = settings.width ?? settings.height %}
{% set height = settings.height ?? settings.width %}
{% set svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'~width~'" height="'~height~'"/>'|url_encode %}
{% set src = 'data:image/svg+xml;charset=utf-8,'~svg %}
{% set attributes = attributes|merge({src: src}) %}
{% set attributes = attributes|merge({style: placeholderStyle}) %}
{{tag('img', attributes)}}
{% endif %}
{%- endmacro -%}

Macro has three parameters:

  • image - asset object. Don't pass element query to macro, pass specific image object. So instead of entry.someAssetField, use entry.someAssetField.one().
  • settings image transform settings. Need to contain width and/or height for placeholder to appear. Rest of settings will be ignored while generating placeholder.
  • attributes - HTML attributes that will be assigned to <img> element, like class. You can learn more about generating HTML attributes from Twig variables in THIS atricle.

Here's example use of macro:

{% import 'file_with_macro' as m %}

{% set ourImage = entry.someAssetField.one() %}

{% set transformSettings = {
    width: 300,
    height: 400,
    format: 'jpg',
    quality: 95,
} %}

{{m.transformOrPlaceholder(ourImage, transformSettings, {
    class: 'some-class',
}) }}

You can also create a macro that just outputs placeholder image, without generating image transform:

{%- macro placeholder(settings, attributes = {}) -%}
{# settings #}
{% set placeholderStyle = {
    'background-image': 'url(placeholder.jpg);',
    'background-position': 'center;',
    'background-size': 'cover;',
} %}
{# logic #}
{% if settings.width is defined or settings.height is defined %}
{% set width = settings.width ?? settings.height %}
{% set height = settings.height ?? settings.width %}
{% set svg = '<svg xmlns="http://www.w3.org/2000/svg" width="'~width~'" height="'~height~'"/>'|url_encode %}
{% set src = 'data:image/svg+xml;charset=utf-8,'~svg %}
{% set attributes = attributes|merge({src: src}) %}
{% set attributes = attributes|merge({style: placeholderStyle}) %}
{{tag('img', attributes)}}
{% endif %}
{%- endmacro -%}

And if you use Imager X (or old Imager), you can generate placeholder image using placeholder function.

Placeholder macro using external service #

There are many services that provide nicely formatted placeholder images. To obtain such an image, usually you just need to append width and height to URL of placeholder service.

For example - using placehold.co, you can get image with width 600px and height 400px under this address: https://placehold.co/600x400. Images generated by that website have the size of placeholder placed in the middle, in "width x height" format. By tinkering with address, you can also adjust things like font or text and background color.

Neat, right? Just keep in mind that by using external service, you are tying your website to it - and one day such service might just stop working. Or start acting up and generate images really slowly.

Let's use placehold.co service in macro - it will be used in the same way as SVG macro.

{%- macro transformOrPlaceholder(image, settings, attributes = {}) -%}
{% if image is not null %}
{% set src = image.getUrl(settings) %}
{% set attributes = attributes|merge({src: src}) %}
{{tag('img', attributes)}}
{% elseif settings.width is defined or settings.height is defined %}
{% set width = settings.width ?? settings.height %}
{% set height = settings.height ?? settings.width %}
{% set src = 'https://placehold.co/'~width~'x'~height %}
{% set attributes = attributes|merge({src: src}) %}
{{tag('img', attributes)}}
{% endif %}
{%- endmacro -%}

Do you like kittens? With placekitten.com service, you can have placeholder image featuring photo of kitten:

{%- macro transformOrPlaceholder(image, settings, attributes = {}) -%}
{% if image is not null %}
{% set src = image.getUrl(settings) %}
{% set attributes = attributes|merge({src: src}) %}
{{tag('img', attributes)}}
{% elseif settings.width is defined or settings.height is defined %}
{% set width = settings.width ?? settings.height %}
{% set height = settings.height ?? settings.width %}
{% set src = 'http://placekitten.com/'~width~'/'~height %}
{% set attributes = attributes|merge({src: src}) %}
{{tag('img', attributes)}}
{% endif %}
{%- endmacro -%}

TAGS:
#macro
If you want to get latest updates on Craft CMS tutorials and components, follow me on Twitter or subscribe to RSS feed.
Quick links for this article:
Placeholder image macro on github gists
Articles on blog:
  • Frontend testing for Craft CMS websites with Codeception and Cypress
  • Building reactive Craft Commerce product page with Sprig plugin
  • Dynamically generated PDF attachments for Freeform submissions
  • Using template hooks in Craft CMS
  • Alpine JS modal component for Craft CMS
  • Using template UI elements to extend Craft CMS control panel
  • Matrix within a Matrix - possible solutions for Craft CMS
  • Universal email template for Craft CMS
  • Creating attributes table from entry fields in Craft CMS
  • Namespacing forms in Craft CMS
  • Creating map-based navigation for Craft CMS
  • Placeholder image macro for Craft CMS
  • Building AJAX contact form with Craft CMS
  • Using incognito field plugin for Craft CMS
  • Email footer creator made with Craft CMS
  • Infinite scrolling and lazy loading with Craft CMS
  • Using Javascript in Twig templates with Craft CMS
  • Twig templating tips and tricks for Craft CMS
  • Basic SEO functionality for Craft CMS
  • Working with dates in Craft CMS templates
  • Working with SVG images in Craft CMS templates
  • Responsive and lazy-loaded youtube videos with Craft CMS
  • Debugging and inspecting Twig templates in Craft CMS
  • Creating article excerpts with Twig component in Craft CMS
  • Adding favicons to Craft CMS website
  • Truncating text with Twig macros in Craft CMS
  • Universal language switcher for Craft CMS
  • Read time macro for Craft CMS
  • Using attr() function to render HTML attributes in Craft CMS
  • Building dynamic, AJAX based pagination for Craft CMS
  • How to add Disqus comments to Craft CMS website
  • Ellipsis pagination component for Craft CMS
  • Converting email addresses into links using Twig macro
  • Breadcrumb created from URL for Craft CMS
  • Best developer-oriented Craft CMS plugins
  • Search autocomplete component for Craft CMS
  • RSS feed - template component for Craft CMS
  • Testing emails sent by Craft CMS using Mailtrap
  • Quick edit link - Twig component for Craft CMS
  • Filtering entries in control panel using Searchit plugin
  • Fetching routes into Twig templates in Craft CMS


Frontend testing for Craft CMS websites with Codeception and Cypress

Building reactive Craft Commerce product page with Sprig plugin

Dynamically generated PDF attachments for Freeform submissions

Using template hooks in Craft CMS

Alpine JS modal component for Craft CMS

Using template UI elements to extend Craft CMS control panel

Matrix within a Matrix - possible solutions for Craft CMS

Universal email template for Craft CMS

Copyright ©2023 Piotr Pogorzelski