Привет, Хабр!
Сегодня я хотел бы рассказать о ряде практик, позволяющих оптимизировать загрузку и отрисовку изображений на сайте. Давайте рассмотрим, что мы можем сделать на сегодняшний день помимо стандартных методик (компрессии и кеширования на клиенте).
Мотивация
Основной мотивацией к оптимизации, как и ранее, являются:
Уменьшение нагрузки на интернет-канал.
Уменьшение потребления CPU при отрисовке изображений.
Также давайте вспомним, что у нас есть метрики Google’s Core Web Vitals (LCP, CLS, FID), на их значения существенно влияет оптимизация работы с изображениями.
Ленивая загрузка
Мы определяем некоторые ресурсы как менее важные, чтобы отложить их загрузку до того момента, когда они станут действительно необходимы. Таким образом можно снизить нагрузку на сеть и процессор в конкретный момент времени.
Например, вы посещаете приложение новостного издания, главная страница которого состоит из списка статей с превью. В каждом превью есть сопроводительное изображение. Очевидно, что вам не нужны изображения статей, которые сейчас находятся за пределами экрана, до тех пор, пока пользователь не начал листать страницу вниз.
С помощью атрибута loading элемента img
можно указать браузеру на необходимость отложить загрузку изображений до тех пор, пока пользователь не дойдет до этапа взаимодействия с этим изображением, например, до пролистывания страницы.
<img src="..." loading="lazy" />
Сегодня атрибут loading
поддерживается не всеми браузерами. Поэтому технику ленивой загрузки можно реализовать также с помощью data-атрибутов и JavaScript.
Ленивая отрисовка
Техника ленивой отрисовки тоже может значительно улучшить скорость загрузки вашего приложения. Суть её в том, что браузер отрисовывает DOM-элементы только тогда, когда они необходимы. Это отчасти похоже на вышеописанную ленивую загрузку, только здесь браузер откладывает на будущее не загрузку, а именно отрисовку. Техника применима не только к изображениям, но и к любому DOM-элементу.
При ленивой отрисовке для элементов, которые не попадают во viewport, браузер пропустит этапы Layout и Paint, что позволит сократить time to interactive (TTI).
Прием относительно свежий, так как возник благодаря добавлению в CSS нового свойства — content-visibility. При значении auto
свойство информирует браузер о том, что позиционирование изображения в макете можно отложить до тех пор, пока оно не приблизится к отображаемой пользователю области. И по мере того, как пользователь будет листать страницу сайта, браузер будет определять, насколько изображение приближается к viewport. При достижении определенного расстояния DOM-элементы будут отрисованы, после чего будет загружено изображение.
<style>
img {
content-visibility: auto;
}
</style>
Асинхронное декодирование
Рассмотрим такой пример:
<p>какой-то вступительный текст</p>
<img src="very-big.jpg" />
<p>очень важный для пользователя текст</p>
В этом случае пользователю придется дождаться загрузки большого по размеру изображения, чтобы увидеть следующую за ним важную информацию.
Чтобы избежать такой ситуации, можно использовать атрибут decoding co значением async
. Это позволит браузеру декодировать изображение вне основного потока, избегая нагрузки на процессор и не блокируя дальнейшую отрисовку DOM-элементов. То есть процесс декодирования изображения будет отложен на будущее, а браузер в свою очередь сможет отрисовать всё содержимое, не дожидаясь загрузки изображения.
<p>какой-то вступительный текст</p>
<img src="very-big.jpg" decoding="async" />
<p>очень важный для пользователя текст</p>
Резервирование вертикального пространства
Не так давно браузеры в последних своих версиях научились заранее резервировать в макете пространство для загружаемого изображения, тем самым предотвращая возможный сдвиг макета (CLS). Чтобы браузер смог зарезервировать место под загружаемое изображение, необходимо задать его атрибуты ширины и высоты.
<style>
img {
max-width: 100%;
height: auto;
}
</style>
<img width="1280" height="800" src="..."/>
Или, в качестве альтернативы, для резервирования вертикального пространства можно воспользоваться свойством aspect-ratio.
Адаптивность (srcset и sizes)
С помощью атрибутов srcset и sizes можно указать несколько вариантов одного изображения. Браузер рассчитает и выберет для загрузки тот вариант, который обеспечивает наилучшее соотношение размера и качества изображения для устройства пользователя.
<img
src="picture.jpg"
srcset="
small.jpg 240w,
medium.jpg 300w,
large.jpg 720w
"
sizes="(min-width: 960px) 720px, 100vw"
/>
А если в браузере пользователя включён режим экономии интернет-трафика, то будет выбрано наименьшее по весу изображение.
Blurry placeholder
Blurry placeholder — это техника резервирования пространства с помощью изображения-заглушки, чтобы дать пользователю некоторое представление об изображении, которое в конечном итоге будет загружено.
![Пример Blurry placeholder. Пример Blurry placeholder.](https://habrastorage.org/getpro/habr/upload_files/7b2/502/b4d/7b2502b4dd8db81cf41bf225c990b24f.jpeg)
Одной из рекомендаций по созданию blurry placeholder является использование SVG-изображения в формате data-uri
. Это намного практичнее, чем CSS-фильтры для создания эффекта размытия, потому что в данном случае он реализован на уровне самого SVG-файла. В результате это позволяет повысить производительность интерфейса и снизить нагрузку на процессор.
<style>
img {
background: cover url('data:image/svg+xml;charset=utf-8,...');
}
</style>
<img src="..." />
Заключение
Мы рассмотрели одни из наиболее актуальных сегодня подходов к оптимизации работы с изображениями в вебе. Но это не исчерпывающее руководство, и я буду признателен, если вы поделитесь своим идеям и мыслями в комментариях под этой статьей.