Automating webp production in Jekyll
Assuming you’re happy using webp
– a good quality image format that’s significantly smaller than jpg
– you’ll need to provide a fallback file that every browser can display. You can do this by using the picture
element. For example:
<picture>
<!-- For browsers that can display
webp files -->
<source srcset="your-image-in-webp-format.webp" type="image/webp">
<!-- For browsers that can’t display
webp files -->
<img src="your-image-in-jpg-format.jpg" alt="Alt text" class="bunch of classes">
<!-- Note that all additional attributes,
such as class and alt,
are added to the img element,
and will also apply to the source image. -->
</picture>
If you have a Jekyll website with hundreds of posts and images in jpg
format, you’re not going to retrospectively create new webp
files and then update your HTML. Ideally, you want a system that:
- automatically generates
webp
files from your existing images - automatically generates the correct
picture
-based HTML in your Markdown files - allows you to use one, non-
webp
file when you create future posts
It is possible. In this guide I’m going to assume you:
- know how to install a Jekyll plugin
- generate image HTML with includes (e.g. with a file called
figure.html
)
There may be other ways, but this is how I do it.
1. Install the jekyll-webp plugin
jekyll-webp handles the automatic generation of webp
files from jpg
, jpeg
, png
, tiff
and, if desired, gif
files. It goes through your designated image folder and creates webp
files should they not exist. Note, it puts them directly into your _site
folder, rather than the source directory (which will save you a lot of remote build minutes) and retains the original files.
2. Configure the jekyll-webp plugin
As with most plugins, you can configure some settings in Jekyll’s _config.yml
file. Here’s what I changed – you may want to change other settings depending on your website configuration:
- Set your outputted
webp
quality on a scale of 1-100. The default setting is75
, which appears to hit a sweet spot of quality and smaller file size. - Tell the plugin where you store images. In my case, this is in an imaginatively named
/images
folder (keep the preceding slash)
I also wanted to change the append_ext
setting to true
so that the plugin appended webp
to the filenames it outputs. For example, instead of outputting a new file called image.webp
I wanted image.jpg.webp
, as this would make the next stage simpler. Unfortunately, this doesn’t seem to make any difference to the webp
filename 🤷🏻♂️.
Here are my settings:
# jekyll-webp settings
webp:
enabled: true
# The quality of the webp conversion 0 to 100 (where 100 is least lossy)
quality: 75
# List of directories containing images to optimize, nested directories will only be checked if `nested` is true
# By default the generator will search for a folder called `/img` under the site root and process all jpg, png and tiff image files found there.
img_dir: ["/images"]
# Whether to search in nested directories or not
nested: false
# add ".gif" to the format list to generate webp for animated gifs as well
formats: [".jpeg", ".jpg", ".png", ".tiff"]
# File extensions for animated gif files
gifs: [".gif"]
# Set to true to always regenerate existing webp files
regenerate: false
# Local path to the WebP utilities to use (relative or absolute)
# Omit or leave as nil to use the utilities shipped with the gem, override only to use your local install
webp_path: nil
# List of files or directories to exclude
# e.g. custom or hand generated webp conversion files
exclude: []
# append '.webp' to filename after original extension rather than replacing it.
# Default transforms `image.png` to `image.webp`, while changing to true transforms `image.png` to `image.png.webp`
append_ext: false
3. Use includes to generate your picture HTML
I’ve used a figure.html
include to generate figure
, img
and figcaption
HTML for many years. As we want to change what we output, we’ll need to edit this. This will be the only file we need to edit.
Here’s what the current include looks like (with classes and additional Liquid removed):
<figure>
<img src="/images/{{ include.url }}" alt="{{ include.alt }}">
<figcaption>{{ include.caption }}</figcaption>
</figure>
And here’s what we use in our Markdown posts:
{% include figure.html url="image.jpg" alt="Image alt text." caption="Caption text" %}
We can change our include so it generates a picture
element and automatically creates a webp
filename:
<!--
Automatically create a webp filename.
The jekyll-webp plugin will have created
this file.
It’s in your _site folder.
-->
{% assign webp_filename = include.url | replace: ".jpg", ".webp" | replace: ".jpeg", ".webp" | replace: ".png", ".webp" | replace: ".tiff", ".webp" %}
<figure>
<picture>
<!-- Use the webp file -->
<source srcset="/images/{{ webp_filename }}' type="image/webp">
<!-- Fallback to the file you added -->
<img src="/images/{{ include.url }}" alt="{{ include.alt }}">
</picture>
<figcaption>{{ include.caption }}</figcaption>
</figure>
Note that we don’t have to change what we’ve already entered in our posts possibly hundreds of times as we are passing in the same variables to the include. Nor do we need to create any new images. Our include automatically generates the correct webp
filename by replacing the existing extension in the url
with webp
, just as the plugin does.
For the full code, see the repo.
Previous post Should I use… webp?
Next post Notes on files and folders, and how platforms killed them