Kodokon kodokon.com

Адаптивные изображения: srcset, sizes и picture

Отдавай нужное изображение нужному экрану с помощью srcset и sizes, оставляй picture для художественной адаптации и освой ленивую загрузку.

9 мин · 3 вопросов

Открыть этот урок в Kodokon

Изображения обычно составляют половину веса страницы: это твой первый рычаг производительности. Основной механизм - srcset с дескрипторами w, который объявляет реальную ширину доступных файлов, вместе с sizes, сообщающим предполагаемую ширину отображения. Ключевой момент: браузер выбирает изображение через свой сканер предзагрузки, ещё до того, как рассчитает раскладку CSS. Без sizes он предполагает 100vw и часто скачивает намного больше, чем нужно. На итоговый выбор влияет и плотность экрана: экран 2x на области в 400 px запросит файл примерно на 800 px.

HTML
<img src="harbor-800.jpg"
     srcset="harbor-400.jpg 400w,
             harbor-800.jpg 800w,
             harbor-1600.jpg 1600w"
     sizes="(max-width: 600px) 100vw, 50vw"
     alt="Old harbor at sunset"
     width="800" height="533">
Дескрипторы w + sizes: браузер оптимизирует сам

С srcset/sizes решает браузер: он может отдать более лёгкий вариант в зависимости от плотности экрана или настроек экономии трафика. <picture> переворачивает логику: источник навязываешь ты через <source media> или <source type>. Оставь его для двух случаев: художественная адаптация (другая обрезка на мобильных, а не просто другой размер) и согласование формата (AVIF или WebP с запасным JPEG). Для простого изменения размера picture - лишняя сложность.

HTML
<picture>
  <source media="(max-width: 600px)"
          srcset="hero-square.jpg">
  <source type="image/avif"
          srcset="hero-wide.avif">
  <img src="hero-wide.jpg" alt="Museum facade"
       width="1200" height="600">
</picture>
picture: другая обрезка на мобильных и современный формат с запасным вариантом

Для всего остального на странице loading="lazy" откладывает скачивание, пока изображение не приблизится к области просмотра, - нативно и без JavaScript. Дополни его decoding="async", чтобы декодирование не блокировало отрисовку, и главное - width и height: браузер вычислит соотношение сторон и зарезервирует место, что убирает сдвиги вёрстки (CLS). Для критичного изображения делай противоположное ленивой загрузке: fetchpriority="high".

HTML
<img src="gallery-01.jpg"
     alt="Exhibition hall"
     loading="lazy" decoding="async"
     width="800" height="600">
Изображение за пределами экрана: lazy, async и зарезервированные размеры

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Для чего именно нужен атрибут sizes?
    • Чтобы менять размер изображения средствами CSS
    • Чтобы сообщить предполагаемую ширину отображения и дать браузеру выбрать из srcset
    • Чтобы ограничить максимальный вес скачиваемого файла
  2. В каком случае нужен именно <picture>, а не обычный srcset?
    • Чтобы отдавать одно и то же изображение в нескольких вариантах ширины
    • Для другой обрезки под каждый экран или современного формата с запасным вариантом
    • Чтобы включить нативную ленивую загрузку
  3. Как loading="lazy" повлияет на главное изображение, видимое при загрузке?
    • Никак, на первом экране атрибут игнорируется
    • Отложит его загрузку и испортит LCP
    • Улучшит LCP, повысив приоритет изображения