Создание адаптивных изображений при рендеринге Markdown в Eleventy
Для чего нужны адаптивные изображения
Если сайт просматривается на мобильном устройстве и изображения на странице высокого разрешения, а, следовательно, и большого размера, то они будут выглядеть хорошо, но загрузка сайта через мобильную сеть может быть очень медленной. С другой стороны, если на сайте будут размещены изображения низкого разрешения и небольшого размера, то на мобильных устройствах они будут загружаться быстро, но на мониторах с высоким разрешением эти изображения будут выглядеть размыто.
Адаптивные изображения – это набор методов, используемых для загрузки изображений подходящего размера, в зависимости от разрешения устройства, ориентации, размера экрана, сетевого подключения и макета страницы. Браузер не должен растягивать изображение, чтобы оно соответствовало макету страницы, а загрузка изображения не должна приводить к потере времени и трафика. Это улучшает взаимодействие с посетителями сайта, поскольку изображения загружаются быстро и выглядят чёткими на любом устройстве.
Адаптивные изображения в Eleventy
Eleventy предлагает разработчикам готовый плагин, позволяющий решить проблему адаптивных изображений с минимальными усилиями.
Для этого, сначала устанавливаем плагин, выполнив команду из корня проекта:
# terminal
npm install @11ty/eleventy-img
Затем, в конфигурационном файле Eleventy, подключаем плагин:
// .eleventy.js
...
const img = require("@11ty/eleventy-img");
...
Далее, в конфигурационном файле Eleventy, добавляем функцию-обработчик шорткода, генерирующую адаптивный HTML-код и изображения в различных разрешениях:
// .eleventy.js
...
function imgShortcode(src, alt, cls, sizes) {
const options = {
widths: [460, 620, 780, 940, 1100],
formats: ["webp", "jpeg"]
};
img(src, options);
const attributes = {
alt: alt,
class: cls,
sizes: sizes,
};
const metadata = img.statsSync(src, options);
return img.generateHTML(metadata, attributes);
}
...
В параметре widths
указывается массив размеров изображений (по ширине), которые должен сформировать плагин из исходного изображения (высота изображений будет пропорциональной), а в параметре formats
- массив форматов генерируемых изображений. Всего, в этом примере, плагин создаст 10 вариантов изображений - 5 размеров в формате webp
и 5 размеров в формате jpeg
.
Чтобы можно было использовать подготовленный шорткод в шаблонах Nunjucks, включаем его в конфигурацию Eleventy:
// .eleventy.js
...
module.exports = (config) => {
...
config.addNunjucksShortcode("img", imgShortcode);
...
};
Теперь, в шаблонах Nunjucks, можно использовать этот шорткод следующим образом:
// page.njk
{% img "path/image.png", "Аlt name", "class1 class2", "70vw" %}
В шорткод передаётся 4 параметра:
- наименование исходного изображения и путь к нему,
- альтернативное наименование изображения (атрибут
alt
), - классы стилей изображения (атрибут
class
), - ширина изображения при различных разрешениях экрана (атрибут
sizes
).
Здесь нужно отметить, что в параметры шорткода вынесены только те свойства изображения, которые зависят от конкретной страницы сайта и её вёрстки.
На выходе получим примерно такой HTML-код:
<!-- page.html -->
<img
alt="Аlt name"
class="class1 class2"
src="/images/JBdBZcXjYP.jpeg"
width="1100"
height="576"
srcset="
/images/JBdBZcXjYP-460.webp 460w,
/images/JBdBZcXjYP-620.webp 620w,
/images/JBdBZcXjYP-780.webp 780w,
/images/JBdBZcXjYP-940.webp 940w,
/images/JBdBZcXjYP-1100.webp 1100w
"
sizes="70vw" />
С адаптивными изображениями в шаблонах разобрались, но с изображениями в Markdown не все так просто.
Адаптивные изображения в Markdown
Когда редактор сайта вставляет изображение в текст страницы, Markdown создаёт следующий код:
<!-- post.md -->

Этот код, при рендеринге Markdown, преобразуется в простой (не адаптивный) HTML-тег:
<!-- post.html -->
<img alt="Аlt name" src="/images/image.png" />
Для того, чтобы изображения Markdown преобразовывались в адаптивные, необходимо переопределить метод рендеринга изображений Markdown, задействовав для этого шорткод, который уже подготовлен и успешно используется в шаблонах Nunjucks.
Для этого, в конфигурационном файле Eleventy, создаём свой экземпляр объекта markdown-it
с необходимыми свойствами:
// .eleventy.js
...
const markdown = require("markdown-it")({
html: true,
breaks: true,
linkify: true,
});
...
Далее переопределяем метод renderer.rules.image
созданного объекта markdown
для обработки изображений с помощью нашего шорткода:
// .eleventy.js
...
markdown.renderer.rules.image = (tokens, idx) => {
const token = tokens[idx];
return imgShortcode(
token.attrGet("src"),
token.content,
"class1 class2",
"70vw"
);
};
...
И последнее - в конфигурации Eleventy заменяем системный объект markdown-it
на вновь созданный с переопределённым методом рендеринга изображений:
// .eleventy.js
...
module.exports = (config) => {
...
config.setLibrary("md", markdown);
...
};
Результирующий код будет примерно таким:
// .eleventy.js
...
const img = require("@11ty/eleventy-img");
function imgShortcode(src, alt, cls, sizes) {
const options = {
widths: [460, 620, 780, 940, 1100],
formats: ["webp", "jpeg"]
};
img(src, options);
const attributes = {
alt: alt,
class: cls,
sizes: sizes,
};
const metadata = img.statsSync(src, options);
return img.generateHTML(metadata, attributes);
}
...
const markdown = require("markdown-it")({
html: true,
breaks: true,
linkify: true,
});
markdown.renderer.rules.image = (tokens, idx) => {
const token = tokens[idx];
return imgShortcode(
token.attrGet("src"),
token.content,
"class1 class2",
"70vw"
);
};
...
module.exports = (config) => {
...
config.addNunjucksShortcode("img", imgShortcode);
config.setLibrary("md", markdown);
...
};
Теперь, все изображения, вставленные в Markdown, будут обрабатываться нашим шорткодом с автоматической генерацией адаптивного HTML-кода и изображений в разных разрешениях.