Responsive Images with Jekyll and ImageMagick
The Jekyll plugin described here is now available, if you just want to get it installed.
A responsive design adapts to display size to improve the user experience. An example is a grid layout that increases the number of columns with the width of the screen, from one on a narrow mobile device, to several on a wide screen display. A responsive design is made up of responsive design elements, among them responsive images, which help to:
- deliver appropriately sized and compressed variants of images to minimize transfer time and optimize performance,
- deliver appropriate content at those various sizes, e.g. using simpler artwork for smaller icons, rather than merely shrinking larger artwork, to preserve clarity.
We address the first motivation, showing how to automate image resizing for Jekyll sites by using ImageMagick command-line tools.
HTML essentials
Responsive images are enabled by two attributes of the HTML img
element:
srcset
, providing a list of available image variants and their widths, andsizes
providing a list of context-specific hints.
An img
element should also provide the common src
, alt
, width
and height
attributes. Putting them all together, it should look something like this:
Here, the srcset
attribute provides three image variants:
example-w256.jpg
of width 256 pixels,example-w512.jpg
of width 512 pixels, and- the original
example.jpg
of width 1024 pixels.
The sizes
attribute provides guidance as to the context in which the image appears:
- if the viewport width is up to 575 pixels (
575px
) then there is one column (100vw
i.e. 100% of viewport width), - if the viewport width is up to 767 pixels (
767px
) then there are two columns (50vw
i.e. 50% of viewport width), - if the viewport width is up to 991 pixels (
991px
) then there are three columns (34vw
—rounding up), - otherwise there are four columns (
25vw
).
This suggests that the image will appear as part of a one to four column layout, depending on display width.
Automating srcset
is achievable; we do so here. Automating sizes
is much more difficult as its value depends on the context in which the image appears; we do not attempt to do so here.
The particular breakpoints chosen above are derived from those in Bootstrap.
ImageMagick essentials
ImageMagick is a command-line tool that can query and modify images in a wide variety of formats. We use its convert
tool for resizing images:
Here, we convert example.jpg
to example-256w.jpg
, stripping meta data (-strip
) setting the quality (JPEG compression in this case) to 30, and resizing to a width of 256 pixels (the height will be scaled proportionally).
We also use ImageMagick’s identify
tool to obtain the widths and heights of images:
The -ping
option avoids consuming the entire file to obtain this information. The -format
option gives the output format, in this case the width and height separated by a comma ('%w,%h'
). The output will be e.g. 1024,768
.
ImageMagick has numerous libraries available for various programming languages. However, we will use the command-line interface directly to minimize dependencies, given that our needs are simple.
Jekyll plugin
We now develop a Jekyll plugin that automates image resizing for a given set of widths. For convenience, it also provides filters to set srcset
, width
and height
attributes.
Configuration
Add the following to the site’s _config.yml
:
This configures the widths of resized images and their quality. The choice of widths
should cover the typical sizes of images as they appear on the site. The choice of quality (between 0 and 100) is a trade-off between file size (lower at lower quality) and clarity (higher at higher quality). It could be tuned by eye. Low quality can be very satisfactory with the prevalence of high definition displays.
For indii.org, where most images are photos, I find noticeable degradation in thumbnail quality at 20, but little at 30. That thumbnails link to original high-resolution images also permits the quality to be reduced. For
widths
values I iterated with PageSpeed Insights to assess performance, and settled on the above configuration.
Installation
The plugin requires ImageMagick. It is standard in Linux distributions and available through Homebrew on macOS. If not already, it can be installed with e.g.:
OS | Command |
---|---|
Ubuntu | apt-get install imagemagick |
Fedora | dnf install ImageMagick |
openSUSE | zypper install ImageMagick |
macOS | brew install imagemagick |
If you happen to be hosting with CloudFlare Pages, it is already installed.
Copy the Ruby code below to _plugins/jekyll-responsive-magick.rb
:
Usage
The plugin provides three filters: srcset
, width
and height
. Each consumes an absolute path to an image (as it would appear in src
) and generates a value for the corresponding attribute. The intended usage is:
src
must be an absolute path, i.e. beginning with /
, such as /assets/example.jpg
. This is necessary for the plugin to find the right file in your project.
With the plugin installed and one or more uses of the srcset
, width
or height
filters, you can build your site as normal, now with responsive images.
Testing
To test that responsive images are working, try:
- Inspecting the rendered HTML of pages in the
_site
directory, or via your browser by right-clicking and selecting “View source”. Verify that thesrcset
,width
andheight
attributes are set correctly. - In your browser, right clicking an image and selecting “Open image in new tab” (works with Firefox, Chromium and Chrome). Verify that the expected image variant has been used by inspecting the URL of the new tab. It should have a name such as
example-w256.jpg
, where256
denotes the resized width. - Checking your page with PageSpeed Insights to verify that appropriate image variants are being selected for different devices.
Further details
The srcset
, width
and height
filters call ImageMagick’s convert
and identity
on demand, rather than for all image assets in a project. Caching is used to call identity
at most once per image per build, and convert
once per image per width, storing resized images in a subdirectory _responsive/
for reuse in subsequent builds. Resized images in _responsive/
are updated only if their original source image changes (detected using last modified times on files).
If you experience any issues with outdated images, or simply wish to clean up, remove the whole _responsive/
directory and rebuild. You may also wish to do this if you change the widths
option in _config.yml
.
When using width
and height
, expect additional build time of about one second per 100 images due to the overhead of launching identity
processes.
When using srcset
for the first time, expect additional build time on the order of minutes as resized images are generated with convert
. Performance will improve drastically on subsequent builds because of the _responsive/
subdirectory.
Summary
With a combination of a plugin and ImageMagick, we can automate the addition of the srcset
attribute to img
elements for Jekyll sites, creating responsive images to minimize transfer time and optimize website performance.