Cloudinary Blog

How I used Cloudinary to solve responsive image needs in my Jekyll website, and shared the magic in a plugin

By Nicolas Hoizey
Plugin for Automatic Responsive Image HTML Code Generation

This is a guest post by Nicolas Hoizey, co-founder of Clever Age and creator of the Jekyll Cloudinary plugin. Nicolas’ plugin leverages Cloudinary’s image storage, optimization, resizing, and delivery infrastructures to automate responsive images in Jekyll-generated static sites. We think it’s the bee’s knees, and invited Nicolas to write a bit about the process and motivation behind it. Without further ado, here’s Nicolas.

I recently migrated my personal website to the latest major version of Jekyll, and took the opportunity to re-think my toolchain.

Some of the plugins that I’d been using were not satisfying my needs for responsive images, so I decided to find other ways to fulfill these needs.

To generate the responsive images HTML (do I really need to say that using native responsive images should be a no-brainer nowadays?), I tried the Jekyll Responsive Image plugin. It is really nice; it lets you define your own image markup templates, which means you can use srcset or <picture> as you like. But it didn’t address all of my concerns:

  • Generating a Jekyll site from scratch with this plugin requires generating all images’ variants from the master images. I currently have around 750 images on my blog, leading to some very long build times.
  • Sending all these variants to the server also takes quite some time, because I don’t have fast network access at home.
  • And of course, all these images are served from the same server as the pages, which in my case is cheap (but nice) shared hosting.

I wanted a simplified and faster workflow, and less load on the server side.

Most of the responsive web sites that my company builds for clients use ad-hoc solutions for responsive images, but I was aware of a few SaaS responsive image solutions, so I decided to check if any of them would fit my needs.

Cloudinary is one of the most feature-rich solutions available, and it can even be used for free if your needs are reasonable. It's not easy for other solutions to compete with that…

With a free account, I could test whatever I wanted, try different features, and decide to continue or look elsewhere.

The main features I was looking for, which Cloudinary provides, are:

  • The ability to use the service as a proxy: the master images are stored on my hosting, but all images delivered to my visitors come from Cloudinary, generated on the fly from the masters. Even better, I don’t need to manually upload the master images – Cloudinary fetches them automatically from my local, published versions. In other words, the only “client” for my originals is Cloudinary. As a result, the bandwidth for images on my hosting is really low.
  • Image cropping and resizing options: right now, I am only scaling my images down from large masters to fit responsive layouts. But I’m definitely looking at the possibility of doing advanced art direction using Cloudinary’s magical automatic cropping features.
  • Image format optimization: if I publish JPEG images in my posts, Cloudinary can send WebPs to visitors if their browser supports them. Last month, two thirds of the images delivered by Cloudinary to my visitors were WebPs, which Cloudinary generated and served for me, automatically. That’s a huge win for both my visitors’ performance and data plans, and for my Cloudinary bandwidth quota.
  • Image compression optimization: Cloudinary is able to compute the best compression level to lower the weight of each image while keeping the visual quality high.

Convinced that Cloudinary offered everything I needed, I still had to develop a Jekyll plugin that used these features.

After some consideration, I decided to start with a {% cloudinary %} Liquid tag that would ease image publication with Cloudinary, while still being relatively easy to develop. I took inspiration from other plugins, found help on StackOverflow when needed, and finally released the first version of the Jekyll Cloudinary plugin in July 2016.

The syntax is pretty straightforward:

{% cloudinary [preset] path/to/img.jpg alt="alt text" caption="image caption" %}

From this input, the plugin outputs responsive image HTML, using the srcset and sizes attributes for the <img> tag (see the “varying size and density” section of this post to understand how these attributes work, and this post which explains why you should use them instead of <picture>, most of the time). The srcset and fallback src contain Cloudinary URLs that fetch the post’s master images on-the-fly and resize them to several, alternate sizes.

For example, as shown in the documentation, this code in a Markdown file:

{% cloudinary logo /assets/logos/cloudinary.png alt="Cloudinary logo" %}

will generate this HTML code:

  srcset="<cloud_name>/image/fetch/c_limit,w_80,q_auto,f_auto/https://<domain>/assets/logos/cloudinary.png 80w,<cloud_name>/image/fetch/c_limit,w_240,q_auto,f_auto/https://<domain>/assets/logos/cloudinary.png 240w,<cloud_name>/image/fetch/c_limit,w_400,q_auto,f_auto/https://<domain>/assets/logos/cloudinary.png 400w"
    (min-width: 50rem) 13rem,
    (min-width: 40rem) 25vw,
  alt="Cloudinary logo"

You are in full control of the number of generated images, their resolutions, and the sizes attribute (which helps the browser decide which image to download). This control comes from the configuration options you can use in your _config.yaml. Here is the part of my configuration file where I defined rules for logos:

      min_width: 80
      max_width: 400
      fallback_max_width: 200
      steps: 3
      sizes: '(min-width: 50rem) 13rem, (min-width: 40rem) 25vw, 45vw'
      figure: never
        class: logo
  • cloud_name: … is your personal ID from Cloudinary
  • presets: starts the list of presets you define for your site
  • logo: is the name of one of my presets, which I use in the Liquid tag before the name of the image file
  • min_width: 80 defines the narrowest generated image
  • max_width: 400 defines the widest generated image
  • fallback_max_width: 200 defines the fallback (src) image width
  • steps: 3 defines the number of images to generate
  • sizes: '(min-width: 50rem) 13rem, (min-width: 40rem) 25vw, 45vw' defines the sizes attribute of the responsive image, which depends on the design and breakpoints
  • figure: never prevents generation of a full <figure>/<img>/<figcaption> element (I often don't want them on logos)
  • attributes: starts a list of attributes to always add to generated <figure> and/or <img> elements
  • class: logo adds a class attribute with a logo value, which I use in my CSS to make sure the logo never takes more than one fourth of its container width, and is floated right

You can define all of these rules, for any number of presets that you need.

With this plugin and my free Cloudinary account, the build time of my site has been reduced by 90%, the storage on my server has been reduced by 60%, and I don't have to worry about image optimization anymore. Huge wins.

Where to go from here? Originally, I wanted to allow writers to use the simple standard Markdown syntax for images, but I have not managed to build this yet, despite some valuable answers to my questions from Jekyll lead maintainer Parker Moore himself. I'll have to dig deeper into Jekyll hooks in the future.

At the end of the day, this was a great way to learn a bit of Ruby, a bit about the Jekyll internals, how plugins work, and how to build and release a gem… I’ve learned so much in a short period of time thanks to this useful little pet project.

Of course, help is welcome to make the plugin even better. There are already a few issues open for bugs or things that should be added to the plugin. Feel free to add your bug reports and ideas, or even contribute through pull requests!

Recent Blog Posts

The Visual Media Report: Visual Engagement and User Experience

With privacy top of mind, we wondered what we might learn from analyzing the large volume of data. What user behaviors would we discover, what regional differences might exist? What insights or early hints from different industries could we extrapolate? These questions guided us as we analyzed millions of anonymous end-user experiences and asset interactions across our platform.

Read more
How a Cloud-native DAM Platform Optimizes Customer Experiences

In today’s digital age, brands rely heavily on rich media to tell stories, foster engagement, and make emotional connections that drive results. Marketers use videos and images, tuned to customers’ interests, to create dynamic visual experiences. Digital campaigns about trips to Florida, for instance, have separate plot lines, depending on audiences’ passions for golf, deep sea fishing, or kid-friendly versus romantic getaways. Marketers expect to detect preferences, produce personalized experiences highlighting different desires, and turn digital prospects into vacationing customers. The ultimate success of a marketing campaign relies on the consistent delivery of these customer experiences, at scale.

Read more
Cloudinary’s Media Developer Experts Program

Cloudinary was founded by developers and developer-centric thinking is in our DNA. Our work with developers helps them better understand all things rich-media management and delivery is crucial to us. Now, in an effort to recognize, support, and reward the innovative leaders in that technical community, we’re excited to introduce a new Media Developer Experts (MDE) program! MDEs will leverage the Cloudinary platform to foster a community of media-management professionals; receive training and certifications to become experts within their field or audience; advance the state of media management, adoption, and best practices; and make the web more accessible.

Read more
An Eye-Opening Talk: Building Apps for the Next Billion Users in Africa

William (iChuloo) Imoh, who hails from Lagos, Nigeria, recently embarked on a U.S. speaking tour, February 20-March 12, during which he powwowed with technical and product teams and communities at such renowned enterprises as Netlify, Pluralsight, Lucidchart, Twilio, and more in Salt Lake City, Dallas, Las Vegas, and San Francisco. On March 5, he gave an enlightening talk, entitled International Developers and Development: Building for the Next Billion Users at Cloudinary in Santa Clara, California. Below is a synopsis. For details, see the related slides.

Read more
The Debut of the Cloudinary Customer Advisory Board

Focus on customers has always been Cloudinary’s mantra. Because we owe them our success, we are constantly reaching out to our customers, not just for feedback on our offerings, but also for their vision, wish list, and buy-in of what Cloudinary can do to meet their needs and make them succeed. About six months ago, it occurred to us that it would be beneficial if we could meet regularly with those who are behind innovation at our key customers—executives, product gurus, developers, content managers—to swap strategies, product roadmaps, best practices, and such. In particular, we’d like to solicit actionable feedback as a foundation for our plans of product enhancements.

Read more