{"id":13612129,"url":"https://github.com/nhoizey/jekyll-cloudinary","last_synced_at":"2025-04-06T06:14:29.027Z","repository":{"id":41262813,"uuid":"62938314","full_name":"nhoizey/jekyll-cloudinary","owner":"nhoizey","description":"Jekyll plugin adding a Liquid tag for Cloudinary, for better responsive images","archived":false,"fork":false,"pushed_at":"2023-08-24T04:41:09.000Z","size":305,"stargazers_count":90,"open_issues_count":28,"forks_count":18,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-02T03:17:03.136Z","etag":null,"topics":["cloudinary","image","jekyll","jekyll-plugin","performance","responsive"],"latest_commit_sha":null,"homepage":"https://nhoizey.github.io/jekyll-cloudinary/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nhoizey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-07-09T07:36:35.000Z","updated_at":"2025-02-23T07:34:10.000Z","dependencies_parsed_at":"2024-01-14T04:49:29.241Z","dependency_job_id":"1bc73288-9b64-4a29-b4fe-ade249ae53a6","html_url":"https://github.com/nhoizey/jekyll-cloudinary","commit_stats":{"total_commits":255,"total_committers":13,"mean_commits":"19.615384615384617","dds":0.5254901960784314,"last_synced_commit":"7e376894e6525aab518e761d12b36c097d58d238"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhoizey%2Fjekyll-cloudinary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhoizey%2Fjekyll-cloudinary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhoizey%2Fjekyll-cloudinary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nhoizey%2Fjekyll-cloudinary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nhoizey","download_url":"https://codeload.github.com/nhoizey/jekyll-cloudinary/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247441063,"owners_count":20939239,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloudinary","image","jekyll","jekyll-plugin","performance","responsive"],"created_at":"2024-08-01T20:00:23.003Z","updated_at":"2025-04-06T06:14:29.002Z","avatar_url":"https://github.com/nhoizey.png","language":"Ruby","readme":"# Jekyll Cloudinary Liquid tag\n[![Build](https://github.com/nhoizey/jekyll-cloudinary/actions/workflows/rubocop.yml/badge.svg)](https://github.com/nhoizey/jekyll-cloudinary/actions/workflows/rubocop.yml)\n\u003c!--\n[![Gem Version](https://badge.fury.io/rb/jekyll-cloudinary.svg)](https://badge.fury.io/rb/jekyll-cloudinary)\n[![Gem Downloads](https://img.shields.io/gem/dt/jekyll-cloudinary.svg?style=flat)](http://rubygems.org/gems/jekyll-cloudinary) --\u003e\n\n`jekyll-cloudinary` is a [Jekyll](http://jekyllrb.com/) plugin adding a [Liquid](http://liquidmarkup.org) tag to ease the use of [Cloudinary](https://nho.io/cloudinary-signup) for responsive images in your Markdown/[Kramdown](http://kramdown.gettalong.org/) posts.\n\nIt builds the HTML for responsive images in the posts, using the `srcset` and `sizes` attributes for the `\u003cimg /\u003e` tag (see [the \"varying size and density\" section of this post](https://jakearchibald.com/2015/anatomy-of-responsive-images/#varying-size-and-density) if this is new for you, and why it's recommended to [not use `\u003cpicture\u003e` most of the time](https://cloudfour.com/thinks/dont-use-picture-most-of-the-time/)). URLs in the `srcset` are cloudinary URLs that [fetch on-the-fly](http://cloudinary.com/features#fetch) the post's images and resize them to several sizes.\n\nYou are in full control of the number of generated images and their sizes, and the `sizes` attribute that helps the browser decide which image to download. See the complete configuration options for details.\n\nHere is the general syntax of this Liquid tag:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary cloudflare.png alt=\"Un schéma montrant l'apport de Cloudflare\" caption=\"Un schéma montrant l'apport de Cloudflare\" loading=\"lazy\" %}\n```\n\u003c!-- {% endraw %} --\u003e\n\n\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n## Table of contents\n\n- [Jekyll Cloudinary Liquid tag](#jekyll-cloudinary-liquid-tag)\n  - [Table of contents](#table-of-contents)\n  - [Installation](#installation)\n  - [Configuration](#configuration)\n    - [Mandatory settings](#mandatory-settings)\n    - [Optional global settings](#optional-global-settings)\n      - [`only_prod` (default: `false`)](#only_prod-default-false)\n      - [`verbose` (default: `false`)](#verbose-default-false)\n      - [`origin_url`](#origin_url)\n    - [Optional (but highly recommended) presets](#optional-but-highly-recommended-presets)\n      - [Default preset](#default-preset)\n      - [Additional presets](#additional-presets)\n    - [Detailed preset settings](#detailed-preset-settings)\n      - [`figure` (default: `auto`)](#figure-default-auto)\n      - [`min_width` (default: `320`)](#min_width-default-320)\n      - [`max_width` (default: `1200`)](#max_width-default-1200)\n      - [`fallback_max_width` (defaut: `1200`)](#fallback_max_width-defaut-1200)\n      - [`steps` (default: `5`)](#steps-default-5)\n      - [`sizes` (default: `\"100vw\"`)](#sizes-default-100vw)\n      - [`attributes` (default: none)](#attributes-default-none)\n  - [Liquid tag values](#liquid-tag-values)\n  - [Liquid tag attributes](#liquid-tag-attributes)\n    - [Recommended attributes](#recommended-attributes)\n    - [Loading attribute](#loading-attribute)\n    - [Other interesting attributes](#other-interesting-attributes)\n  - [Live example](#live-example)\n  - [Contributing](#contributing)\n  - [Do you use the plugin on a live site?](#do-you-use-the-plugin-on-a-live-site)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\n## Installation\n\n[Sign up **for free** on Cloudinary!](https://nho.io/cloudinary-signup) The free account should be enough for most blogs.\n\nAdd `gem 'jekyll-cloudinary'` to the `jekyll_plugin` group in your `Gemfile`:\n\n```ruby\nsource 'https://rubygems.org'\n\ngem 'jekyll'\n\ngroup :jekyll_plugins do\n  gem 'jekyll-cloudinary'\nend\n```\n\nThen run `bundle` to install the gem.\n\n## Configuration\n\n### Mandatory settings\n\nAdd `cloudinary` to your `_config.yml` and your Cloudinary \"Cloud name\" (find it in your [Cloudinary dashboard](https://cloudinary.com/console)):\n\n```yaml\ncloudinary:\n  cloud_name: \u003cput here your Cloudinary \"Cloud name\"\u003e\n```\n\n### Optional global settings\n\nYou can now define some global settings\n\n```yaml\ncloudinary:\n  …\n  only_prod: true\n  verbose: true\n  origin_url: https://another-domain.com\n```\n\n#### `only_prod` (default: `false`)\n\nWhen set to `true`, this setting implies that responsive image HTML and Cloudinary URLs are generated only if the environment is `production`.\n\nFor example:\n\n- if you run `JEKYLL_ENV=production bundle exec jekyll build`, you'll get the code to deploy, with `srcset` and Cloudinary URLs.\n- if you run `JEKYLL_ENV=development bundle exec jekyll serve`, you'll get code for local development, with standard `\u003cimg src=\"…\"\u003e` code and local URLs.\n\n[`JEKYLL_ENV=development` is the default value](https://jekyllrb.com/docs/configuration/#specifying-a-jekyll-environment-at-build-time).\n\nIf you don't set `only_prod` or set it to `false`, responsive image HTML and Cloudinary URLs are always generated, whatever the environment. jekyll-cloudinary had only this behavior before version 1.11.0.\n\n#### `verbose` (default: `false`)\n\nWhen set to `true`, this setting will show messages in the console when something goes wrong, such as:\n\n```\n[Cloudinary] Couldn't find this image to check its width: /path/to/jekyll/_site/assets/img.jpg\n```\n\nor\n\n```\n[Cloudinary] Natural width of source image 'img.jpg' (720px) in _posts/2016-06-09-post.md not enough for creating 1600px version\n```\n\n#### `origin_url`\n\nWhen `origin_url` is set, **jekyll-cloudinary** will use this URL rather than `site.url` as origin of the source images.\n\nThis allows you to store your source image on a different domain than your website.\n\n### Optional (but highly recommended) presets\n\nYou can now define the presets you need for your posts' images, starting with the default one:\n\n#### Default preset\n\nThe default preset is the one you don't even have to mention when using the Liquid tag, and that will be used if a preset you use in the tag doesn't exist.\n\n```yaml\ncloudinary:\n  …\n  presets:\n    default:\n      min_width: 320\n      max_width: 1600\n      fallback_max_width: 800\n      steps: 5\n      sizes: \"(min-width: 50rem) 50rem, 90vw\"\n```\n\nThis preset will generate five images 320 to 1600 pixels wide in the `srcset` and define `sizes` as `\"(min-width: 50rem) 50rem, 90vw\"`. The fallback image defined in the `src` will have a width of 800 pixels.\n\nWith this preset, you only have to write this in your Markdown post:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary /assets/img.jpg alt=\"beautiful!\" %}\n```\n\u003c!-- {% endraw %} --\u003e\n\nTo get this HTML:\n\n```html\n\u003cimg\n  src=\"http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_800,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg\"\n  srcset=\"\n    http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_320,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg 320w,\n    http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_640,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg 640w\n    http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_960,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg 960w\n    http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_1280,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg 1280w\n    http://res.cloudinary.com/\u003ccloud_name\u003e/image/fetch/c_limit,w_1600,q_auto,f_auto/https://\u003cyour-domain\u003e/assets/img.jpg 1600w\n    \"\n  sizes=\"(min-width: 50rem) 50rem, 90vw\"\n  alt=\"beautiful!\"\n  width=\"480\"\n  height=\"320\"\n/\u003e\n```\n\nThere is a true default `default` preset, but you're strongly encouraged to override it with your own default preset.\n\n#### Additional presets\n\nYou can add other presets if you need several image sizes in your posts.\n\nHere is an example for images that take only one third of the post width:\n\n```yaml\ncloudinary:\n  …\n  presets:\n    …\n    onethird:\n      min_width: 110\n      max_width: 535\n      fallback_max_width: 300\n      steps: 3\n      sizes: \"(min-width: 50rem) 17rem, 30vw\"\n      attributes:\n        class: \"one3rd\"\n        loading: \"lazy\"\n```\n\nTo use this additional preset, you will have to write this in your Markdown post:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary onethird /assets/img.jpg %}\n```\n\u003c!-- {% endraw %} --\u003e\n\nThe generated element will also get a `class=\"one3rd\"` that can be useful for example with this CSS:\n\n```css\n.one3rd {\n  max-width: 33%;\n  float: right;\n  margin: 0 0 1em 1em;\n}\n```\n\n### Detailed preset settings\n\n#### `figure` (default: `auto`)\n\nThis setting lets you decide what to do when there is a `caption` attribute in the Cloudinary Liquid tag.\n\nThe value can be:\n\n- `auto` (default): will generate a `\u003cfigure\u003e` and `\u003cfigcaption\u003e` only if there's a caption\n- `never`: will always generate a `\u003cimg\u003e`, losing the caption\n- `always`: will always generate a `\u003cfigure\u003e` and `\u003cfigcaption\u003e`, even if there's no `caption` attribute\n\nIf a `\u003cfigure\u003e` is generated and there are attributes (in the preset or the Liquid tag), they are added to the `\u003cimg\u003e` if they are `alt`, `title` or `loading`, or to the `\u003cfigure\u003e`.\n\n#### `min_width` (default: `320`)\n\n#### `max_width` (default: `1200`)\n\n#### `fallback_max_width` (defaut: `1200`)\n\n#### `steps` (default: `5`)\n\n#### `sizes` (default: `\"100vw\"`)\n\n#### `attributes` (default: none)\n\nYou can define attributes that will be added to all images using this preset. Attributes are added without transformation to the generated element.\n\nYou should obviously not add to preset attributes that should have different values for each image, such as `alt`, `caption`, `title`, etc.\n\nYou can set a `class`, `aria-*` attributes for enhanced accessibility, or even `data-*` attributes you would like to use later with CSS or JavaScript.\n\n## Liquid tag values\n\nYou can use liquid variables inside the liquid tag.\n\nFor example, if you have the picture path in a `thumbnail` attribute of the YAML Front Matter, you can use it in the tag:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary {{ page.thumbnail }} alt=\"{{ page.title }} image\" %}\n```\n\u003c!-- {% endraw %} --\u003e\n\n## Liquid tag attributes\n\nYou can add attributes to the liquid tag, after the image path:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary onethird /assets/selfie.jpg alt=\"My selfie\" loading=\"eager\" %}\n```\n\u003c!-- {% endraw %} --\u003e\n\nJust like the ones from the preset settings, inline attributes are added without transformation to the generated element.\n\n### Recommended attributes\n\nYou should obviously define the `alt` attribute, mandatory for accessibility.\n\nIf you want the image to be inside a `figure` element, you probably also want to add a `caption` attribute. This is the only one that can act differently than other attributes, depending on [the `figure` setting](#figure-default-auto).\n\nYou can also set a `title` attribute, but there are really few use cases for it on images.\n\n`alt`, `caption` and `title` attributes can contain Markdown.\n\n### Loading attribute\n\nThe `loading` attribute allows you to tell the browser how you want it to load this image.\n\nFrom [this article written by Addy Osmani](https://addyosmani.com/blog/lazy-loading/):\n\n\u003e The loading attribute allows a browser to defer loading offscreen images and iframes until users scroll near them. loading supports three values:\n\u003e - `lazy`: is a good candidate for lazy loading.\n\u003e - `eager`: is not a good candidate for lazy loading. Load right away.\n\u003e - `auto`: browser will determine whether or not to lazily load.\n\u003e \n\u003e Not specifying the attribute at all will have the same impact as setting loading=auto.\n\n### Other interesting attributes\n\nYou can also use attributes to add a `class`, `aria-*` attributes for enhanced accessibility, or even `data-*` attributes you would like to use later with CSS or JavaScript.\n\n## Live example\n\nGo to this post: [https://nicolas-hoizey.com/2016/07/tout-change-rien-ne-change.html](https://nicolas-hoizey.com/2016/07/tout-change-rien-ne-change.html).\n\nThe source Markdown is here: [https://github.com/nhoizey/nicolas-hoizey.com/blob/master/_posts/2016/07/13-tout-change-rien-ne-change/2016-07-13-tout-change-rien-ne-change.md](https://github.com/nhoizey/nicolas-hoizey.com/blob/master/_posts/2016/07/13-tout-change-rien-ne-change/2016-07-13-tout-change-rien-ne-change.md).\n\nThe content is in french, yes, but look only at the images if you don't understand.\n\nYou'll find here:\n\n- 2 logos floating on the right of the text (or centered on smaller screens): [Jekyll](http://jekyllrb.com/) and [Cloudinary](https://nho.io/cloudinary-signup)\n- 2 screenshots taking the whole width of the content: the [Cloudinary pricing table](http://cloudinary.com/pricing), and [Dareboost](https://www.dareboost.com/en/home)'s performance monitoring graph\n\nThese image types need different settings to deal with different sizes and position:\n\n- screenshot always use the full content width, if they're wide enough\n- logos are centered and take one half of the content width on small screens, and are floated and take one fourth of the content width on larger screens\n\nThis is how I use the Cloudinary Liquid tag for the Cloudinary logo and prices table screenshot:\n\n\u003c!-- {% raw %} --\u003e\n```liquid\n{% cloudinary logo /assets/logos/cloudinary.png alt=\"Logo de Cloudinary\" %}\n{% cloudinary cloudinary-pricing.png alt=\"Les tarifs de Cloudinary\" caption=\"Les tarifs de Cloudinary, dont l'offre gratuite déjà généreuse\" %}\n```\n\u003c!-- {% endraw %} --\u003e\n\nThe only difference is that I explicitly use the `logo` preset for the logo. The other image uses the `default` preset.\n\nHere is the necessary configuration for this:\n\n```yaml\ncloudinary:\n  cloud_name: …\n  verbose: false\n  presets:\n    default:\n      min_width: 320\n      max_width: 1600\n      fallback_max_width: 800\n      steps: 5\n      sizes: '(min-width: 50rem) 50rem, 90vw'\n      figure: always\n    logo:\n      min_width: 80\n      max_width: 400\n      fallback_max_width: 200\n      steps: 3\n      sizes: '(min-width: 50rem) 13rem, (min-width: 40rem) 25vw, 45vw'\n      figure: never\n      attributes:\n        class: logo\n```\n\nIt generates these HTML fragments (pretty printed here), for the logo:\n\n```html\n\u003cimg\n  src=\"https://res.cloudinary.com/nho/image/fetch/c_limit,w_200,q_auto,f_auto/https://nicolas-hoizey.com/assets/logos/cloudinary.png\"\n  srcset=\"\n    https://res.cloudinary.com/nho/image/fetch/c_limit,w_80,q_auto,f_auto/https://nicolas-hoizey.com/assets/logos/cloudinary.png 80w,\n    https://res.cloudinary.com/nho/image/fetch/c_limit,w_240,q_auto,f_auto/https://nicolas-hoizey.com/assets/logos/cloudinary.png 240w,\n    https://res.cloudinary.com/nho/image/fetch/c_limit,w_400,q_auto,f_auto/https://nicolas-hoizey.com/assets/logos/cloudinary.png 400w\"\n  sizes=\"\n    (min-width: 50rem) 13rem,\n    (min-width: 40rem) 25vw,\n    45vw\"\n  class=\"logo\"\n  alt=\"Logo de Cloudinary\"\n  width=\"480\"\n  height=\"350\"\n/\u003e\n```\n\nAnd for the screenshot:\n\n```html\n\u003cfigure\u003e\n  \u003cimg\n    src=\"https://res.cloudinary.com/nho/image/fetch/c_limit,w_800,q_auto,f_auto/https://nicolas-hoizey.com/2016/07/cloudinary-pricing.png\"\n    srcset=\"\n      https://res.cloudinary.com/nho/image/fetch/c_limit,w_320,q_auto,f_auto/https://nicolas-hoizey.com/2016/07/cloudinary-pricing.png 320w,\n      https://res.cloudinary.com/nho/image/fetch/c_limit,w_640,q_auto,f_auto/https://nicolas-hoizey.com/2016/07/cloudinary-pricing.png 640w,\n      https://res.cloudinary.com/nho/image/fetch/c_limit,w_960,q_auto,f_auto/https://nicolas-hoizey.com/2016/07/cloudinary-pricing.png 960w,\n      https://res.cloudinary.com/nho/image/fetch/c_limit,w_1208,q_auto,f_auto/https://nicolas-hoizey.com/2016/07/cloudinary-pricing.png 1208w\"\n    sizes=\"(min-width: 50rem) 50rem, 90vw\"\n    alt=\"Les tarifs de Cloudinary\"\n    width=\"1208\"\n    height=\"561\"\n  /\u003e\n  \u003cfigcaption\u003eLes tarifs de Cloudinary, dont l'offre gratuite déjà généreuse\u003c/figcaption\u003e\n\u003c/figure\u003e\n```\n\nThere are only 4 version in the `srcset` here because 2 of the 5 expected sizes are larger than the source image, and are replaced by one using the native source image width.\n\nAnd here are the relevant parts of the accompanying CSS (in Sass form):\n\n```sass\narticle {\n  figure, img {\n    margin: 2em auto;\n    display: block;\n    max-width: 100%;\n    height: auto;\n  }\n}\n\n.logo {\n  display: block;\n  margin: 1em auto;\n  max-width: 50%;\n  height: auto;\n\n  @media (min-width: 40em) {\n    max-width: 25%;\n    float: right;\n    margin: 0 0 1em 1em;\n  }\n}\n```\n\n## Contributing\n\nThanks for your interest in contributing! There are many ways to contribute to this project. [Get started here](./CONTRIBUTING.md).\n\n## Do you use the plugin on a live site?\n\nAdd it to [the \"Sites\" page of the wiki](./wiki/Sites) and please let us know on Twitter: [@mavaddat](https://twitter.com/mavaddat)  [@nhoizey](https://twitter.com/nhoizey)\n","funding_links":[],"categories":["Images \u0026 Pictures","Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhoizey%2Fjekyll-cloudinary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnhoizey%2Fjekyll-cloudinary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnhoizey%2Fjekyll-cloudinary/lists"}