В настоящее время изображения являются крупнейшим активом Интернета с точки зрения общего объёма передаваемых данных и количества запросов на страницу. Средний размер передаваемой веб-страницы по состоянию на июнь 2022 года составляет примерно 2 Мб, причём одни только изображения занимают почти половину этого показателя. Не будет преувеличением сказать, что оптимизация изображений может стать самой большой оптимизацией производительности, которую вы можете сделать.
Позже вы узнаете как развивались адаптивные изображения, с целью решить проблемы, возникающие из-за попыток использовать одно изображение на все случаи жизни. В этом разделе вы узнаете о ключевых показателях производительности, связанных с изображениями, и о том, как их улучшить.
Отсрочка загрузки изображений
Хотя в дальнейшем вы узнаете несколько способов, как сделать запросы к изображениям минимальными и эффективными, самым быстрым всегда будет тот, который никогда не выполнится. Поэтому сразу хочу сказать, что это, возможно, самое важное изменение, которое вы можете сделать для пользователей: атрибут loading="lazy".
<img src="image.jpg" loading="lazy" alt="…">
Данный атрибут гарантирует, что запросы к изображениям не будут выполняться до тех пор, пока они не попадут в область просмотра пользователя. Это позволяет отложить запросы к изображениям при начальной загрузки страницы — времени, когда браузер наиболее загружен, исключая эти запросы из критического потока визуализации.
Как бы просто это ни было на практике, использование атрибута loading может оказать огромное положительное влияние на производительность: изображение, которое никогда не попадёт в область просмотра пользователя, никогда не будет затребовано, тем самым полоса пропускания не будет тратиться на изображения, которые пользователь никогда не увидит.
Однако есть одна загвоздка: откладывая эти запросы, вы не используете преимущества максимально оптимизированных процессов браузеров, позволяющих запрашивать изображения как можно ранее. Если использовать loading="lazy" для элементов <img>, расположенных в верхней части макета, а значит, с большой вероятностью находящихся в области просмотра пользователя при первой загрузке страницы, — эти изображения могут показаться пользователю значительно медленнее.
Приоритет выборки
Атрибут loading — это пример масштабных усилий в области веб-стандартов, направленных на то, чтобы дать разработчикам больше возможностей самим определять приоритеты запросов в браузерах.
Вы, вероятно, знаете об основных подходах браузеров к выбору приоритета: например, запрос внешнего CSS-файла в разделе <head> документа считается достаточно важным, чтобы заблокировать визуализацию, а запрос внешнего JavaScript-файла перед </body> будет отложен до завершения визуализации. Если значение атрибута loading в <img> установлено как lazy, соответствующий запрос к изображению будет отложен до тех пор, пока браузер не определит, что изображение будет показано пользователю. В противном случае изображение будет иметь тот же приоритет, что и любое другое изображение на странице.
Атрибут fetchpriority предназначен для того, чтобы дать разработчикам более детальный контроль над активами, позволяя отмечать приоритет ресурсов как «высокий» и «низкий» по отношению к ресурсам того же типа. Варианты использования fetchpriority аналогичны атрибуту loading, но гораздо шире. Например, вы можете использовать fetchpriority="low" для изображения, которое появляется только после взаимодействия с пользователем (независимо от того, попадает ли это изображение в область просмотра пользователя или нет), чтобы отдать приоритет видимым изображениям в других местах страницы, или fetchpriority="high" для приоритета изображения, которое, как вы знаете, будет сразу же видно в области просмотра, как только страница будет показана.
Обратите внимание, что fetchpriority отличается от атрибута loading тем, что не меняет поведение браузера. Он не указывает браузеру загружать определённые активы раньше других, а даёт ему жизненно важный контекст для принятия решений о запросе активов.
Измерение влияния изображений
При оптимизации графических ресурсов воспринимаемая производительность зачастую важнее и труднее поддается измерению, чем их общий передаваемый размер.
Web Vitals предлагает измеримые, действенные метрики и рекомендации по улучшению взаимодействия пользователей с Интернетом, выявляя такие проблемы, как низкая скорость ответа веб-сервера, проблемы с отображением и задержки при взаимодействии с пользователем. Core Web Vitals — подмножество этих целей, ориентированное на непосредственное взаимодействие пользователя с отдельной страницей — набор технических показателей, которые вместе определяют, насколько быстрым кажется пользователю тот или иной процесс.
Кумулятивное смещение макета
Метрика «Кумулятивное смещение макета» (Cumulative Layout Shift, CLS) — показатель визуальной стабильности. Это метрика определяет, насколько сильно смещается содержимое на странице по мере загрузки активов и отображения страницы. Любой, кто провёл много времени в Интернете, терял место чтения в длинном тексте из-за того, что страница «прыгала», когда внезапно отображался запаздывающий шрифт или источник изображения, или когда интерактивный элемент внезапно сдвигался в сторону от указателя. Высокий CLS — это в лучшем случае неприятность, а в худшем причина ошибки пользователя: например, кнопка «Отмена» перемещается на место, ранее занятое кнопкой «Подтвердить», именно в тот момент, когда пользователь на неё нажимает .
Учитывая долгое время загрузки изображений и количество места, которое они могут занимать в макете, вполне логично, что изображения являются частой причиной высоких показателей CLS.
<style>
img {
max-width: 25em;
height: auto;
}
p {
font-size: 1.4em;
line-height: 1.4;
}
</style>
<div>
<img src="image/aquilegia.jpg" alt="">
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique consectetur reiciendis ea aliquam molestiae deserunt dignissimos.</p>
<img src="image/pansies.jpg" alt="">
<p>Commodi modi nemo quia doloremque excepturi eveniet repellendus, tempore eos laudantium et necessitatibus rerum?</p>
<img src="image/geranium-sylvaticum.jpg" alt="">
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique consectetur reiciendis ea aliquam molestiae deserunt dignissimos.</p>
</div>
Благодаря недавним внесённым изменениям, в современных браузерах избежать высоких значений CLS из-за изображений стало проще, чем вы думаете.
Если вы работаете над интерфейсами уже несколько лет, то знакомы с атрибутами width и height для <img>: до широкого распространения CSS это был единственный способ контролировать размер изображения.
<img src="image.jpg" height="200" width="400" alt="…">
Эти атрибуты вышли из употребления в попытке отделить проблемы стиля от разметки, особенно когда адаптивный веб-дизайн сделал необходимым указание размеров в процентах с помощью CSS. В ранние дни адаптивного веб-дизайна распространённым советом было «удалить неиспользуемые атрибуты width и height», поскольку значения, которые мы указывали в CSS — max-width: 100% и height: auto должны были их заменить.
<img src="image.jpg" alt="…">
img {
max-width: 100%;
height: auto;
}
После удаления атрибутов height и width, как это показано в примере выше, единственный метод, с помощью которого браузер может определить высоту изображения в этой ситуации, — это запросить источник, проанализировать его и отобразить с присущим ему соотношением сторон на основе ширины пространства, которое он занимает в макете после применения таблицы стилей. Большая часть этого процесса происходит после того, как страница отображается, при этом вновь рассчитанная высота вызывает дополнительные сдвиги макета.
Начиная с 2019 года, поведение браузера было обновлено, чтобы по-разному обрабатывать атрибуты width и height. Вместо использования значений этих атрибутов для определения фиксированного размера элемента <img> в макете на основе пикселей, можно считать, что эти атрибуты представляют соотношение сторон изображения, хотя синтаксис остался тем же. Современные браузеры делят одно значение на другое, тем самым определяют соотношение сторон элемента <img> ещё до отображения страницы. Это позволяет браузеру зарезервировать пространство, которое будет занимать изображение при отображении макета.
Как правило, вы всегда должны использовать атрибуты height и width в элементе <img> со значениями, соответствующими собственному размеру вашего источника изображения, при условии, что указали height: auto и max-width: 100% до переопределения высоты из атрибута HTML.
<img src="image.jpg" height="200" width="400" alt="…">
img {
max-width: 100%;
height: auto;
}
Используя атрибуты width и height для элементов <img> вы избежите высоких показателей CLS из-за изображений.
<style>body {
display: flex;
}
img {
max-width: 100%;
height: auto;
}
div {
width: 50%;
}
</style>
<div>
<h1>С<code>height</code>/<code>width</code></h1>
<img src="image/aquilegia.jpg" alt="" height="1000" width="1000">
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique consectetur reiciendis ea aliquam molestiae deserunt dignissimos, commodi modi nemo quia doloremque excepturi eveniet repellendus, tempore eos laudantium et necessitatibus rerum?</p>
</div>
<div>
<h1>Без <code>height</code>/<code>width</code></h1>
<img src="image/aquilegia.jpg" alt="">
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Similique consectetur reiciendis ea aliquam molestiae deserunt dignissimos, commodi modi nemo quia doloremque excepturi eveniet repellendus, tempore eos laudantium et necessitatibus rerum?</p>
</div>
Важно отметить, что у такого подхода нет недостатков, поскольку он опирается на давно устоявшееся поведение браузеров. Любой браузер с поддержкой базового CSS будет работать так, как он это делал всегда — атрибуты height и width в вашей разметке будут переопределяться стилями.
Хотя атрибуты width и height позволяют ловко избежать проблем с CLS, резервируя необходимое пространство для размещения изображений, показывать пользователям пустой участок или низкокачественный заполнитель, пока они ждут загрузки и отображения изображения, тоже не идеально. Хотя есть вещи, которые можно сделать, чтобы смягчить ощутимое и заметное влияние медленно загружающихся изображений, единственный способ быстрее представить пользователю полностью готовое изображение — это уменьшить его размер при передаче.
Наибольший содержательный фрагмент
Метрика «Наибольший содержательный фрагмент» (Largest Contentful Paint, LCP) измеряет время, необходимое для отрисовки самого большого «содержательного» элемента, видимого в области просмотра пользователя, — элемента, занимающего наибольший процент видимой части страницы. На первый взгляд может показаться, что это слишком специфическая метрика, но она служит практическим косвенным показателем того момента, когда с точки зрения пользователя была отрисована большая часть страницы. LCP важнейший показатель (воспринимаемой) производительности.
Такие метрики, как DOMContentLoaded или событие window.onload, могут быть полезны для определения того, когда процесс загрузки текущей страницы технически завершён, но они не обязательно соответствуют восприятию страницы пользователем. Небольшая задержка при отрисовке элемента за пределами области просмотра пользователя будет учтена в любой из этих метрик, но, скорее всего, останется совершенно незамеченной пользователем в реальности. Долгий LCP означает, что первое впечатление пользователя от страницы — наиболее важного содержимого в текущей области просмотра, заключается в том, что страница работает медленно или вообще не работает.
Восприятие пользователя, отражённое в LCP, оказывает непосредственное влияние на пользовательский опыт. Эксперимент, проведённый компанией Vodafone в прошлом году, показал, что улучшение LCP на 31% привело не только к увеличению продаж на 8%, что само по себе является сильным результатом, но и к увеличению на 15% общего числа пользователей, которые стали потенциальными клиентами (показатель привлечения посетителей), и на 11% числа пользователей, просмотревших корзину (показатель пользователей, добавивших товар в корзину).
Более чем на 70% веб-страниц самым крупным элементом в начальной области просмотра является изображение — либо отдельный элемент <img>, либо элемент с фоновым изображением. Другими словами, 70% оценок LCP страниц основаны на работе с изображениями. Не нужно обладать богатым воображением, чтобы понять, почему: большие, привлекающие внимание изображения и логотипы с высокой вероятностью будут находиться «над сгибом».
Есть несколько шагов, которые можно предпринять, чтобы избежать задержек LCP: во-первых, никогда не указывайте loading="lazy" для изображений «над сгибом», поскольку задержка запроса до окончательного отображения страницы, скорее всего, окажет сильное негативное влияние на ваш показатель LCP. Во-вторых, использование fetchpriority="high" может сообщить браузеру, что передача этого изображения должна быть приоритетнее других изображений на странице.
Учитывая эти правила, самое важное, что вы можете сделать для улучшения показателей LCP страницы, — это сократить время, необходимое для передачи и отображения изображений. Для этого вам нужно сделать источники изображений как можно меньше и эффективнее (разумеется, без ущерба для их качества) и убедиться, что пользователи получают только те изображения, которые наиболее целесообразны для их контекста просмотра.
Заключение
Изображения — это самый большой расход полосы пропускания для ваших пользователей — пропускная способность, которая отнимается у всех остальных ресурсов, необходимых для отображения страницы. Изображения создают значительные проблемы с точки зрения воспринимаемой производительности как во время, так и после отрисовки макета страницы. Короче говоря, изображения наносят вред.
Как бы это ни было пугающе, но фраза «Интернет был бы лучше, если бы в нём было меньше изображений», безусловно, верна только с точки зрения производительности, но не пользователей. Изображения — жизненно важная часть Интернета, и не стоит жертвовать качеством содержимого ради одной лишь производительности.
В продолжении этого руководства вы узнаете о технологиях, на которых основаны наши графические ресурсы, и о методах снижения их влияния на производительность без ущерба для качества.