Отложенная загрузка изображений для веб-сайтов на уровне браузера
Наконец-то появилась встроенная отложенная загрузка!
Наконец-то появилась поддержка отложенной загрузки изображений для веб-сайтов на уровне браузера! В этом видео показана демонстрация функции:
Начиная с Chrome 76, можно использовать атрибут loading
для отложенной загрузки изображений без необходимости писать собственный код отложенной загрузки или использовать отдельную библиотеку JavaScript. Давайте разберем подробнее.
Совместимость с браузером #
<img loading=lazy>
поддерживается большинством популярных браузеров на базе Chromium (Chrome, Edge, Opera) и Firefox. Реализация для WebKit (Safari) находится на стадии разработки. На сайте caniuse.com есть подробная информация о кросс-браузерной поддержке. Браузеры, не поддерживающие атрибут loading
, просто игнорируют его без каких-либо побочных эффектов.
Зачем нужна отложенная загрузка на уровне браузера? #
По данным Интернет-архива, изображения являются наиболее востребованным типом ресурсов для большинства веб-сайтов и обычно занимают большую часть полосы пропускания. В 90-м процентиле сайты отправляют около 4,7 МБ изображений на настольные и мобильные устройства. Это очень много картинок с котиками.
В настоящее время есть два способа отложить загрузку скрытых изображений:
- использование API Intersection Observer;
- использование обработчиков событий
scroll
,resize
илиorientationchange
.
Любой из этих вариантов позволяет разработчикам добавить функциональность отложенной загрузки. Кроме того, многие разработчики создали сторонние библиотеки, предоставляющие слои абстракций, которые еще проще использовать. Однако если отложенная загрузка поддерживается непосредственно браузером, то необходимость во внешней библиотеке отпадает. Отложенная загрузка изображений на уровне браузера гарантирует, что эта функция будет работать, даже если JavaScript отключен на клиенте.
Атрибут loading
#
Chrome уже умеет загружать изображения с разными приоритетами в зависимости от их расположения относительно области просмотра устройства. Изображения, расположенные ниже области просмотра, имеют более низкий приоритет загрузки, но всё равно загружаются как можно быстрее.
В Chrome 76+ можно использовать атрибут loading
чтобы полностью отложить загрузку скрытых изображений, которые можно получить с помощью прокрутки:
<img src="image.png" loading="lazy" alt="…" width="200" height="200">
Атрибут loading
поддерживает следующие значения:
auto
: поведение браузера при отложенной загрузке по умолчанию, равносильно отсутствию атрибута;lazy
: загрузку ресурса отлаживается до тех пор, пока он не достигнет расчетного расстояния от области просмотра;eager
: ресурс загружается немедленно, независимо от его расположения на странице.
Пороговые значения расстояния от области просмотра #
Все изображения, которые находятся в верхней части страницы, то есть доступны для немедленного просмотра без прокрутки, загружаются в обычном режиме. Изображения ниже области просмотра устройства подгружаются только тогда, когда пользователь прокручивает страницу почти до них.
Реализация механизма отложенной загрузки в Chromium направлена на то, чтобы скрытые изображения загружались до того, как пользователь докрутит страницу до них. Подгружая соседние изображения заранее, мы увеличиваем вероятность того, что они уже будут загружены до момента попадания в область просмотра.
Пороговые значения в Chromium заданы более строго, чем в JavaScript-библиотеках для отложенной загрузки изображений, чтобы соответствовать ожиданиям разработчиков.
Пороговое значение расстояния не является фиксированным и зависит от ряда факторов:
- тип получаемого ресурса изображения;
- использование упрощенного режима в Chrome для Android;
- эффективный тип подключения.
Значения по умолчанию для различных типов эффективных соединений можно найти в исходном коде Chromium. Эти цифры и даже подход, при котором выборка выполняется только при достижении определенного расстояния от области просмотра, могут измениться в ближайшем будущем, поскольку команда Chrome совершенствует эвристику для определения момента начала загрузки.
Улучшенная экономия данных и пороговые значения расстояния от области просмотра #
По состоянию на июль 2020 года Chrome внес значительные улучшения в выравнивание пороговых значений расстояния до области просмотра при отложенной загрузке изображений, чтобы больше соответствовать ожиданиям разработчиков.
При быстром подключении (например, 4G) мы уменьшили пороговое значение расстояния от области просмотра с 3000 пикселей
до 1250 пикселей
, а при более медленном подключении (например, 3G) изменили пороговое значение с 4000 пикселей
до 2500 пикселей
. Эти изменения позволяют добиться следующих двух улучшений:
<img loading=lazy>
больше соответствует тому, что предлагают библиотеки отложенной загрузки JavaScript;- новые пороговые значения расстояния от области просмотра по-прежнему обеспечивают загрузку изображений к тому моменту, когда они попадают в область просмотра в результате прокрутки.
Ниже приведено сравнение между старыми и новыми пороговыми значениями расстояния от области просмотра для одной из наших демонстраций при быстром соединении (4G):
Сравнение старых и новых пороговых значений:
Сравнение новых пороговых значений с LazySizes (популярной JavaScript-библиотекой для отложенной загрузки):
Мы сотрудничаем с сообществом веб-стандартов, чтобы лучше согласовать подходы к пороговым значениям расстояния от области просмотра в разных браузерах.
Изображения должны включать атрибуты размеров #
Когда браузер загружает изображение, он не сразу узнает его размеры, если они не указаны явно. Чтобы браузер мог зарезервировать достаточно места на странице для изображений, рекомендуется, чтобы все теги <img>
включали атрибуты width
и height
. Без указания размеров могут произойти смещения макета, более заметные на страницах, которые загружаются дольше.
<img src="image.png" loading="lazy" alt="…" width="200" height="200">
В качестве альтернативы укажите значения размеров непосредственно во встроенном стиле:
<img src="image.png" loading="lazy" alt="…" style="height:200px; width:200px;">
Метод установки размеров применяется к тегам <img>
независимо от того, используется ли отложенная загрузка, но в этом случае полезность данного метода возрастает. Установка width
и height
также позволяет современным браузерам определять внутренний размер изображений.
В большинстве сценариев отложенная загрузка изображений применяется, даже если размеры изображений не указаны, но есть несколько нестандартных ситуаций, о которых следует знать. Без задания width
и height
размеры изображения сначала равны 0×0 пикселей. Если у вас есть галерея таких изображений, браузер может решить, что все они изначально помещаются в область просмотра, так как практически не занимают места и не вытесняются за пределы экрана. В этом случае браузер определяет, что все они видны пользователю, и решает загрузить эти изображения.
Кроме того, задание размеров изображения снижает вероятность смещения макета. Если у вас нет возможности указать размеры изображений, их отложенная загрузка может стать компромиссом между экономией сетевых ресурсов и потенциально большим риском смещения макета.
Хотя отложенная загрузка в Chromium реализована таким образом, что изображения, вероятно, будут загружены, как только они станут видимыми, всё же существует небольшая вероятность того, что этого не произойдет. В этом случае отсутствие width
и height
на таких изображениях увеличивает их влияние на совокупное смещение макета.
Для изображений, определенных с помощью <picture>
, также можно применять отложенную загрузку:
<picture>
<source media="(min-width: 800px)" srcset="large.jpg 1x, larger.jpg 2x">
<img src="photo.jpg" loading="lazy">
</picture>
Хотя браузер решает, какое изображение загружать из любого из элементов <source>
, атрибут loading
должен быть включен только в резервный элемент <img>
.
Избегайте отложенной загрузки изображений, которые находятся в первой видимой области просмотра #
Вам следует избегать установки loading=lazy
для любых изображений, которые находятся в первой видимой области просмотра.
Рекомендуется добавлять loading=lazy
только к изображениям, расположенным под областью просмотра, если это возможно. При безотложной загрузке изображения могут быть получены сразу, в то время как при отложенной загрузке браузеру необходимо узнать, где именно на странице расположено изображение, что зависит от наличия IntersectionObserver.
Как правило, любые изображения в области просмотра должны загружаться безотлагательно, используя настройки браузера по умолчанию. Вам не нужно указывать loading=eager
для изображений из области просмотра.
<!-- visible in the viewport -->
<img src="product-1.jpg" alt="..." width="200" height="200">
<img src="product-2.jpg" alt="..." width="200" height="200">
<img src="product-3.jpg" alt="..." width="200" height="200">
<!-- offscreen images -->
<img src="product-4.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-5.jpg" loading="lazy" alt="..." width="200" height="200">
<img src="product-6.jpg" loading="lazy" alt="..." width="200" height="200">
Отказоустойчивость #
Браузеры без поддержки атрибута loading
будут игнорировать его наличие. Хотя эти браузеры не получат преимуществ отложенной загрузки, включение атрибута не окажет на них негативного влияния.
Часто задаваемые вопросы #
Планируется ли автоматическая отложенная загрузка изображений в Chrome? #
Если в Chrome для Android включен упрощенный режим, то Chromium уже автоматически выполняет отложенную загрузку любых изображений, подпадающих под эту категорию. Это в первую очередь предназначено для пользователей, которые заботятся об экономии данных.
Можно ли изменить расстояния до изображения, при которых запускается загрузка? #
Эти значения жестко запрограммированы и не могут быть изменены через API. Однако они могут измениться в будущем, поскольку браузеры экспериментируют с разными пороговыми расстояниями и переменными.
Можно ли атрибут loading
использовать для изображений, заданных через CSS-свойство background? #
Нет, в настоящее время его можно использовать только с тегами <img>
.
Есть ли негативные аспекты отложенной загрузки изображений, которые находятся в пределах области просмотра устройства? #
Безопаснее избегать добавления loading=lazy
в верхней части страницы, поскольку сканер предварительной загрузки в Chrome не будет предварительно загружать изображения с loading=lazy
.
Как атрибут loading
работает с изображениями, которые находятся в области просмотра, но не видны сразу (например, находятся за каруселью или скрыты для определенных размеров экрана с помощью CSS)? #
В отложенном режиме загружаются только изображения, которые находятся на определенном расстоянии от нижней границы области просмотра устройства. Все изображения над областью просмотра, независимо от того, видны ли они в данный момент, загружаются в обычном режиме.
Что делать, если я уже использую стороннюю библиотеку или скрипт для отложенной загрузки изображений? #
Атрибут loading
не должен влиять на код, который в отложенном режиме загружает данные, но важно учитывать некоторые важные моменты:
- Если сторонний загрузчик пытается загрузить изображения или фреймы раньше, чем их будет загружать Chrome в обычном режиме, то есть, на расстоянии, превышающем пороговые значения расстояния от области просмотра, их загрузка всё равно будет отсрочена и они загрузятся согласно стандартным правилам браузера.
- Если сторонний загрузчик использует меньшее расстояние для определения времени загрузки определенного изображения, чем браузер, то браузер будет загружать изображения в отложенном режиме согласно настройкам загрузчика.
Одна из важных причин продолжить использовать стороннюю библиотеку параллельно с loading="lazy"
заключается в предоставлении полизаполнения для браузеров, не поддерживающих данный атрибут.
Как работать с браузерами, которые еще не поддерживают отложенную загрузку? #
Создайте полизаполнение или используйте стороннюю библиотеку для отложенной загрузки изображений на сайт. Свойство loading
можно использовать, чтобы определить, поддерживается ли эта функция в браузере:
if ('loading' in HTMLImageElement.prototype) {
// supported in browser
} else {
// fetch polyfill/third-party library
}
Например, lazysizes — это популярная JavaScript-библиотека отложенной загрузки. Вы можете определить поддержку атрибута loading
, чтобы загружать lazysizes в качестве резервной библиотеки только тогда, когда loading
не поддерживается. Это работает следующим образом:
- Замените
<img src>
на<img data-src>
, чтобы избежать безотложной загрузки в неподдерживаемых браузерах. Еслиloading
поддерживается, заменитеdata-src
наsrc
. - Если
loading
не поддерживается, загрузите запасной вариант (lazysizes) и инициируйте его. Согласно документации по lazysizes, классlazyload
используется как способ указать lazysizes, какие изображения требуют отложенной загрузки.
<!-- Let's load this in-viewport image normally -->
<img src="hero.jpg" alt="…">
<!-- Let's lazy-load the rest of these images -->
<img data-src="unicorn.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="cats.jpg" alt="…" loading="lazy" class="lazyload">
<img data-src="dogs.jpg" alt="…" loading="lazy" class="lazyload">
<script>
if ('loading' in HTMLImageElement.prototype) {
const images = document.querySelectorAll('img[loading="lazy"]');
images.forEach(img => {
img.src = img.dataset.src;
});
} else {
// Dynamically import the LazySizes library
const script = document.createElement('script');
script.src =
'https://cdnjs.cloudflare.com/ajax/libs/lazysizes/5.1.2/lazysizes.min.js';
document.body.appendChild(script);
}
</script>
Вот демонстрация этого паттерна. Запустите его в Firefox или Safari, чтобы увидеть резервный вариант в действии.
Поддерживается ли отложенная загрузка для тега iframe в Chrome? #
Значение <iframe loading=lazy>
недавно стандартизировано и уже реализовано в Chromium. Это позволяет настроить отложенную загрузку iframe с помощью атрибута loading
. Отдельная статья об отложенной загрузке iframe будет вскоре опубликована на web.dev.
Атрибут loading
работает для встроенных фреймов иначе, чем для изображений, так как в учет берется то, является ли iframe скрытым. (Скрытые iframe часто используются для аналитических или коммуникационных целей.) Chrome использует следующие критерии для определения того, является ли iframe скрытым:
- ширина и высота iframe не более 4 пикселей;
- применяются
display: none
илиvisibility: hidden
; - iframe помещается за пределы экрана с использованием отрицательного позиционирования по оси X или Y.
Если iframe соответствует любому из этих условий, Chrome считает его скрытым и в большинстве случаев не загружает его в отложенном режиме. Не скрытые iframe загружаются только тогда, когда они находятся в пределах порогового расстояния от области просмотра. Для встроенных фреймов, которые всё еще загружаются в режиме отложенной загрузки, отображается плейсхолдер.
Как отложенная загрузка на уровне браузера влияет на рекламу на веб-странице? #
Вся реклама, представленная в виде изображений или встроенных фреймов, также загружается в отложенном режиме.
Как обрабатываются изображения при печати веб-страницы? #
Существует нерешенная проблема, связанная с тем, что при печати страницы Chrome должен незамедлительно загрузить все изображения и встроенные фреймы.
Распознает ли Lighthouse отложенную загрузку на уровне браузера? #
В более ранних версиях Lighthouse по-прежнему подчеркивалось, что для страниц, использующих loading=lazy
для изображений, требуется стратегия загрузки закадровых изображений. Lighthouse 6.0 и более новые версии лучше учитывают подходы к отложенной загрузке закадровых изображений, которые могут использовать разные пороговые значения, что позволяет пройти проверку Defer offscreen images (Отложите загрузку закадровых изображений).
Заключение #
Включение поддержки отложенной загрузки изображений может значительно облегчить задачу повышения производительности веб-страниц.
Заметили необычное поведение при включении этой функции в Chrome? Сообщите об ошибке!