How images work in Publii
Publii offers multiple ways to modify and display your images; from basic functionality that simply displays an image, to complex markup that delivers differently-sized images at different screen resolutions to strike the perfect balance between aesthetics and speed.
When creating Publii, we wanted to make sure that the markup used with images was clear and understandable so that even less-experienced users that want to start making their own modifications could jump in and find their way. In this post, we’ll take a look at several ways that we can modify images throughout a theme, but before that, we’ll first need to establish the types of images that Publii uses:
Images Types
Publii utilises four different image types that cover particular elements and areas of a Publii website; each of these types comes its own settings defined through the config.json file in the theme's folder. These types are:
Featured Image - This is an image that is added via the sidebar options on the Edit Post page. Usually, this image will be displayed on the article page itself, and will also be used any time a post preview is displayed, such as on post listing pages such as the Homepage, Tag or Author pages.
Tag Image - Utilized to visually represent tag categories across your site, enhancing the visual appeal of tag-related content.
Author Image - This image goes beyond simple avatars for authors. Instead, it can serve as a dynamic background for author pages or be used to create a visually compelling header that represents the author's persona or brand. Unlike avatars, which are typically small and used to identify the author in a post snippet or comment section, Author Image provide a broader canvas to convey the author's identity, style, or thematic focus.
Content Image - Content images refers to images that are displayed in the post body; that is, if you insert an image into your article via the editor or by dragging and dropping an image into your post, then it will be defined as a content image.
Option Images - These are images that are defined by the creator of a theme to allow images to be uploaded to theme-specific sections of a page via the Theme Options e.g. if a theme has a unique hero section or slider, then the images used in this section will be classed as option images.
Gallery Images - Refers only to images that are uploaded to and used in a Gallery inserted into a post via the Post Editor.
Content Images and Gallery Images are handled by Publii automatically; these are uploaded or inserted via the editor and they have specific predefined settings for this purpose. However, the Featured Image and Option images are more flexible, so we’ll be looking more closely at them and how we can modify their settings in the following sections.
How to setup and use Featured Images in a theme
Basic
The basic markup for an image is very easy to use and understand; it simply pulls the data stored in the FeaturedImage tags, which are detailed in the following link: https://getpublii.com/dev/featured-image-tags/
{{#featuredImage}}
{{#if url}}
<img src="{{url}}" height="{{height}}" width="{{width}}" alt="{{alt}}">
{{/if}}
{{/featuredImage}}
The src, height, width and alt attributes are standard, defining the basic dimensions, the source URL and alt text of the image. Additionally, by using the {{#if url}}
condition, we can check whether a featured image has been uploaded or not; no URL means no image, so the additional functions related to the featured image will be ignored.
Intermediate
The basic markup detailed above will display the RAW (original) images, but what if we want to display responsive thumbnails that will adjust their dimensions depending on the current screen resolution?
Publii has built-in functions to take care of the heavy lifting in this case, so we only have to take care of three elements; setting the number of thumbnails, and defining two other attribute - srcset and sizes.
For example, if we wanted to generate a set of thumbnails, then we would first need to define them in the config.json file. After opening this file, look for the Files section, where we can define the thumbnails using the following code:
"featuredImages": {
"sizes": "(max-width: 48em) 100vw, 768px",
"dimensions": {
"xs": {
"width": 300,
"height": 300,
"crop": true
},
"sm": {
"width": 480,
"height": "auto"
},
"md": {
"width": 768,
"height": "auto"
},
"lg": {
"width": 1024,
"height": "auto"
}
}
The code is quite straightforward. The sizes function is used to define some core rules for how images are displayed, and each item in the dimensions section (e.g. xs, sm etc…in the above example), which is collectively the srcset attribute, defines the specific width for each type of image, from very small to large, which will tell the browser which image to show to the user depending on the size of the viewport. With these attributes set, we can modify the featuredImage markup to make use of these attribute:
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
sizes="{{sizes}}"
srcset="{{srcset}}"
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
The above example can be further simplified by making use of responsiveImageAttributes
helper, which will accept the ‘featuredImage’, srcset and sizes attributes instead of them being separately-defined in the markup:
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
{{responsiveImageAttributes 'featuredImage' srcset sizes}}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
Advanced
Publii offers a lot more options for displaying images for users with more experience. Imagine that you wanted to display a large image in the hero section and a smaller one in other sections of the page. For the hero section we’d need several thumbnails, but for the other(s) we’d only need two or three.
By using the group variable, we can separate them quickly and easily:
"featuredImages": {
"sizes": {
"hero": "(max-width: 1600px) 100vw, 1600px",
"other": "(max-width: 768px) 100vw, 768px"
},
"dimensions": {
"xs": {
"width": 300,
"height": "auto",
"group": "hero,other"
},
"sm": {
"width": 480,
"height": "auto",
"group": "hero,other"
},
"md": {
"width": 768,
"height": "auto",
"group": "hero,other"
},
"lg": {
"width": 1024,
"height": "auto",
"group": "hero"
},
"xl": {
"width": 1360,
"height": "auto",
"group": "hero"
}
}
As you can see, the specific attributes for each group are separately defined in the sizes section, and then each item in the srcset is applied to a particular group using the group attribute. With this done, we can create the markup for the hero section:
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
{{responsiveImageAttributes 'featuredImage' srcset.hero sizes.hero}}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
And a similar markup for the other section:
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
{{responsiveImageAttributes 'featuredImage' srcset.other sizes.other}}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
So as you can see, since all the images in the srcset are added to the hero group, they will all be displayed there, whereas only two images were added to the other group, so only two will be displayed in the other section.
Note: Groups can be created only for Featured images.
Tips: If you want to display only one specific thumbnail you can do this with the following markup, where the dimension name starts with a capital letter {{urlDimension_name}}
{{#featuredImage}}
{{#if url}}
<img src="{{urlXs}}" alt="{{alt}}">
{{/if}}
{{/featuredImage}}
As you notice, a dimension suffix "Xs" was added to the {{url}}
src attribute.
Important: The suffix must start with a capital letter e.g. {{urlSm}}
or {{urlMd}}
Tag Image
Tag images are utilized to represent tag categories on your site visually. Whether it's highlighting a specific topic on tag pages or enhancing the visual appeal of tag listings, these images play a crucial role in the user experience. Here's how to configure and use tag images in your theme.
To set up tag images, you need to define their settings in the config.json file of your theme, similar to how you configure other image types. Below is an example configuration for tag images:
"tagImages": {
"sizes": "100vw",
"dimensions": {
"xs": {
"width": 300,
"height": 200
},
"sm": {
"width": 480,
"height": "auto"
},
"md": {
"width": 749,
"height": "auto"
},
"xl": {
"width": 1200,
"height": "auto"
}
}
To display tag images on your site, use the following Handlebars markup. This example demonstrates how to incorporate responsive and lazy-loaded tag images into a hero section:
{{#featuredImage}}
{{#if url}}
<figure>
<img
src="{{url}}"
{{#if @config.site.responsiveImages}}
{{responsiveImageAttributes 'tagImage' srcset sizes}}
{{/if}}
{{ lazyload "eager" }}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
</figure>
{{/if}}
{{/featuredImage}}
data-is-external-image="true">
Author Image
Author Images serve as a significant visual element, transcending the traditional use of avatars. These images can be employed as expansive background photos for author pages. This approach allows for a more immersive and personalized representation of authors, setting a distinctive tone or theme for their section of the website.
Similar to tag images, author images require configuration in the config.json file. Below is an example setup for author images:
"authorImages": {
"sizes": "100vw",
"dimensions": {
"xs": {
"width": 300,
"height": "auto"
},
"sm": {
"width": 480,
"height": "auto"
},
"md": {
"width": 749,
"height": "auto"
},
"xl": {
"width": 1200,
"height": "auto"
}
}
Using Author images on the front-end follows a similar pattern to tag images. Here's an example of how you might include responsive and lazy-loaded author images in your theme:
{{#featuredImage}}
{{#if url}}
<figure>
<img
src="{{url}}"
{{#if @config.site.responsiveImages}}
{{responsiveImageAttributes 'authorImage' srcset sizes}}
{{/if}}
{{ lazyload "eager" }}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
</figure>
{{/if}}
{{/featuredImage}}
Content Image
As mentioned above, contentImages are handled by Publii so we don’t need to make any changes unless we want to display them in a responsive manner. We can setup this functionality similarly to how we did it above, in the config.json file:
"contentImages": {
"sizes": "(max-width: 48em) 100vw, 768px",
"dimensions": {
"xs": {
"width": 300,
"height": "auto"
},
"sm": {
"width": 480,
"height": "auto"
},
"md": {
"width": 768,
"height": "auto"
}
}
}
Options Image
This type of image can be used when you want to allow your users upload their image via the theme settings, rather than pulling them automatically from post featured images or other areas of the theme, such as for a photo slideshow.
To create this kind of image, we’ll first need to create the attributes for the option in the config.json file, so that we can allow an image to be uploaded:
{
"name": "uploadImage",
"label": "Image",
"group": "Hero section",
"value": "",
"type": "upload",
"upload": true
},
Next, we can create the markup for the image; this function defines the source of the image as an upload, rather than existing content in the theme or post content:
<img src="{{@config.custom.uploadImage}}" alt="">
However, this markup only allows the image to be uploaded; to make them responsive, we’ll need to create the srcset in the config.json as before when we created the Content Images, but in this case we’ll need to add the code to the optionImages section:
"optionImages": {
"sizes": "(max-width: 1600px) 100vw, 1600px",
"dimensions": {
"xs": {
"width": 300,
"height": 255,
"crop": true
},
"sm": {
"width": 480,
"height": "auto"
},
"md": {
"width": 768,
"height": "auto"
},
"lg": {
"width": 1024,
"height": "auto"
},
"xl": {
"width": 1360,
"height": "auto"
} }
}
But these items that we’ve added won’t actually do anything until we expand our image markup to include take the sizes and screen elements into account; once again, the responsiveImageAttributes helper will make this easy:
<img
src="{{@config.custom.uploadImage}}"
{{responsiveImageAttributes @config.custom.uploadImage}}
alt="">
But what about the image dimensions? Not to worry, another helper, {{imageDimensions}}
, will take care of this for us:
<img
src="{{@config.custom.uploadImage}}"
{{responsiveImageAttributes @config.custom.uploadImage}}
{{imageDimensions @config.custom.uploadImage}}
alt="">
With the markup finished, our option image is ready to go!
Gallery images
As with content images, galleryImages is mostly handled by Publii. The only thing that we need to define is the maximum size for thumbnails that are generated by the gallery. We can add this info in the galleryImages section of the config.json file:
"galleryImages": {
"sizes": "",
"dimensions": {
"thumbnail": {
"width": 720,
"height": "auto"
}
}
}
Lazy load
Since version 1.0 Publii has supported native lazy loading that drastically improves your website load-times by loading images only when they appear in the viewport as the user scrolls.
By default this option is enabled (under Site Settings -> Website speed) and works with all content images including gallery thumbnails, iframes, and video elements.
To implement it with other image types such as Featured or Option images we need only add a single helper: {{ lazyload "options" }}
, that can accept the following options:
- lazy
- eager
- auto
Example:
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
{{responsiveImageAttributes 'featuredImage' srcset sizes}}
{{lazyload "lazy"}}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
Note: when the Lazy load option is disabled the helper returns empty output.
Enable the Responsive Images option
Also since version 0.36, Publii has included the option to completely disable thumbnail generation. When disabled, only the RAW (original) image files are provided to a user’s browser.
For Content Images this option works automatically, but for Feature and Option images we have to use a {{@config.site.responsiveImages}}
condition to check if the option is enabled.
{{#featuredImage}}
{{#if url}}
<img
src="{{url}}"
{{#if @config.site.responsiveImages}}
{{responsiveImageAttributes 'featuredImage' srcset.other sizes.other}}
{{/if}}
height="{{height}}"
width="{{width}}"
alt="{{alt}}">
{{/if}}
{{/featuredImage}}
If the Responsive Image option is disabled the sizes and srcset attributes will not be rendered.
In addition to this functionality, you can also utilize the data-responsive="false"
attribute for img tags. When used, this attribute ensures that the srcset and sizes attributes are not added, even if responsive images are enabled.