Автор: Дмитрий Бартошевич (мою фамилию часто пишут как Барташевич)

Эффективные способы оптимизации изображений

Скорость загрузки сайта была в числе моих основных приоритетов еще до настойчивых рекомендаций Google. Один из факторов, влияющих на скорость, — вес изображений. Меньше вес — браузер быстрее показывает страницу. Я пробовал разные способы оптимизации изображений и в результате выбрал несколько, которые использую сам и рекомендую другим.

Стандартный подход

Перед публикацией фотографии на сайте я уменьшаю ее вес. Делаю это в графическом редакторе (Gimp + плагин «gimp-plugin-saveforweb») или сервисе Optimizilla.

Пример
фотография монеты
оригинал, 300px*298px, 102.4 КБ
автор фото — www.flickr.com/photos/simon50000/
оптимизированная с помощью Gimp фотография монеты
оптимизировано в Gimp, 32.4 КБ
открыл фото и сохранил для веб. настройки программы — по умолчанию
оптимизированная с помощью Optimizilla фотография монеты
оптимизировано в Optimizilla, 20.5 КБ
настройки онлайн сервиса — по умолчанию

Уменьшили размер фото — можно публиковать. В код html-страницы добавляем такую строку:

<img src="путь к изображению" alt="описание, что изображено" width="ширина" height="высота" />

Раньше этих действий было достаточно. Сейчас — нет. Назову три причины:

  • Иногда оптимизированные фото на «ретине» выглядят плохо → «ретине» нужно предлагать свои картинки.

  • Появился новый формат изображений — WebP, который делает вес фото еще меньше. Пока формат поддерживается не всеми браузерами → для браузеров, которые «видят» WebP, следует предлагать WebP, а остальным — другие форматы.

  • Чтобы браузеры в смартфонах не отвлекались на адаптацию картинок под размер экрана, нужно предлагать картинки нужного размера сразу. Один размер для смартфонов, другой — для планшетов, третий — для десктопов.

Вместо одной фотографии, одной строчки кода с адресом и описанием следует готовить набор фотографий (разного размера и формата) и указывать в html-коде условия, при которых должна показываться та или иная фотография из набора. Для каждого экрана должно загружаться наиболее релевантное изображение — нужного размера, формата и разрешения.

Новое требование: каждому экрану свое изображение

Принцип «каждому экрану свое изображение» можно реализовать с помощью плагинов: загружаем одну фотографию и плагин автоматически делает копии, меняет размеры и прописывает условия показа. Не нужно сосредотачиваться на технической составляющей работы сайта. Это плюс.

Минусы тоже есть. Во-первых, не все плагины написаны хорошо. Иногда можно здорово проиграть в производительности сайта. Во-вторых, некоторые задачи нельзя решить в автоматическом режиме. Например, кадрирование. Панорамная фотография хорошо смотрится на большом экране, но на смартфоне лучше показать только наиболее значимую часть фотографии.

Показывать разные изображения для разных ситуаций поможет тег <picture>.

Если вы читаете статью со смартфона, ниже вы видите котенка, который спит, свернувшись калачиком. Если читаете с большого экрана — ваш кот зевает и потягивается. Еще есть кот, который сидит и смотрит на вас. Поэкспериментируете с гаджетами или размером окна браузера и убедитесь, что так и есть.

котенок, который меняется в зависимости от ширины экрана монитора
Пример взят отсюда

А вот как это работает:

<picture>
<source media="(min-width: 650px)" srcset="...kitten-large.png" >
<source media="(min-width: 465px)" srcset="...kitten-medium.png" >
<img src="...kitten-small.png" alt="кот" >
</picture>

Атрибут srcset указывает путь изображения для загрузки. Тег <source> и атрибут media указывают условия появления каждой из картинок. Если ширина экрана больше 650px, показывается зевающий кот, если от 465px до 650px — кот сидит. Если экран меньше 465px или если браузер не распознает тег <picture>, вы увидите спящего кота.

В блоге Opera есть 15 примеров использования тега <picture> (англ.). Я заглядываю туда как в шпаргалку по синтаксису: какой код нужен, чтобы для ретины загружать изображения с высоким разрешением, чтобы показывать разные фото для разных экранов, чтобы предлагать WebP там, где браузеры распознают этот формат, чтобы все эти условия указать разом для одного изображения.

updated Для желающих углубиться в тему Вадим Макеев рассказывает, как с помощью image-set можно подключать картинки разных типов и разрешения

А можно ли проще?

С тегом <picture> код картинки занимает иногда более 10 строк, не говоря уже о том, что нужно вручную подготовить несколько вариантов изображения. Если писать 1-2 статьи в месяц, это необременительно. А если у вас интернет-магазин с тысячей наименований и соответствующим количеством фотографий?

Однажды я верстал фотогалерею в flexbox. В зависимости от размера экрана ширина фотографий могла занимать любое значение от 250px до 1200px. Этот диапазон я разбил на интервалы и для каждого подготовил свое изображение со своим размером и форматом. Большой объем ручной работы + неидеальный результат (часто требуемая ширина картинки не совпадала с имеющейся, что расстраивало гугловский pagespeed insight) — все это вынудило меня искать другое решение. И я его нашел — Cloudinary.

C Cloudinary работа по оптимизации изображений сводится к корректировке адреса картинки, загруженной в облако сервиса. Поясню на примере. Давайте войдем в Cloudinary, добавим фотографию монеты из примера выше и скопируем url картинки.

пример работы с Cloudinary

Адрес фото:

//res.cloudinary.com/bartoshevich/image/upload/v1538423803/coin_original.jpg

Все, что требуется, — это после upload/ в адресе добавить q_auto,f_auto/. Новый адрес:

//res.cloudinary.com/bartoshevich/image/upload/q_auto,f_auto/v1538423803/coin_original.jpg

На этом работа по оптимизации картинки завершена. Сервис автоматически изменит качество и формат изображения в зависимости от экрана, на котором открывают адрес картинки. Не нужно готовить много вариантов изображения, прописывать условия для «ретины» и WebP. Все это уже «зашито» в адресе. Код картинки снова умещается в одну строку.

Ниже — оптимизированная с помощью Cloudinary фотография монеты. Если вы откроете статью в разных браузерах (Firefox и Chrome) и сохраните фото, вы получите фотографии разных форматов и веса. У меня скачанная с Chrome фотография весит всего 10.9 КБ — почти в 10 раз меньше оригинала. Код же — одна строка. Нет <picture>, <source>, media и пр.

оптимизированная с помощью Optimizilla фотография монеты

Сотрудники Cloudinary подготовили Cookbook, где описывают возможности сервиса: что можно добавить в адрес изображения и какой результат получить. Например, можно улучшить фотографию, если после upload/ написать в адресе e_improve/. Результат:

оптимизированная с помощью Optimizilla фотография монеты

Иногда я не могу обходиться без тега <picture>. И если тег комбинирую с Cloudinary, «пропуская» адреса изображений через сервис, я использую больше возможностей оптимизации при минимальных усилиях.