picture и srcset
<picture>иsrcset-- механизмы адаптивных изображений в HTML. Они позволяют браузеру выбрать оптимальный файл в зависимости от размера экрана, плотности пикселей и поддерживаемого формата.
Зачем нужно
Один и тот же <img src="photo.jpg"> загрузится и на iPhone (375px), и на 4K мониторе (3840px). Это расточительство трафика на мобильных или размытая картинка на Retina. srcset и <picture> решают это: браузер выбирает из нескольких вариантов, загружая ровно то, что нужно.
Где используется
- Адаптивные изображения на любых сайтах
- Art direction (разные кропы для разных экранов)
- Современные форматы (WebP, AVIF) с fallback
- Retina / HiDPI дисплеи
- Оптимизация Core Web Vitals (LCP)
Предпосылки
srcset -- разные размеры одного изображения
По плотности пикселей (x-дескрипторы)
<!-- 1x для обычных экранов, 2x для Retina -->
<img
src="photo-400.jpg"
srcset="photo-400.jpg 1x,
photo-800.jpg 2x,
photo-1200.jpg 3x"
alt="Фото продукта"
width="400"
height="300"
>
Браузер на Retina (2x) загрузит photo-800.jpg, на обычном -- photo-400.jpg.
По ширине изображения (w-дескрипторы) + sizes
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w,
photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
33vw"
alt="Фото продукта"
>
Как работает:
sizesсообщает браузеру, какую ширину займёт изображение- Браузер вычисляет нужный размер с учётом DPR (device pixel ratio)
- Из
srcsetвыбирается ближайший подходящий файл
Экран 375px (1x DPR):
sizes → 100vw = 375px
Нужно: 375px → выберет photo-400.jpg (400w)
Экран 375px (2x DPR, Retina):
sizes → 100vw = 375px
Нужно: 375 * 2 = 750px → выберет photo-800.jpg (800w)
Экран 1400px (1x DPR):
sizes → 33vw = 462px
Нужно: 462px → выберет photo-800.jpg (800w)
picture -- art direction и форматы
Art direction (разные кропы)
<picture>
<!-- Мобильные: вертикальный кроп -->
<source
media="(max-width: 600px)"
srcset="hero-mobile.jpg 600w,
hero-mobile-2x.jpg 1200w"
sizes="100vw"
>
<!-- Планшеты: квадратный кроп -->
<source
media="(max-width: 1024px)"
srcset="hero-tablet.jpg 1024w,
hero-tablet-2x.jpg 2048w"
sizes="100vw"
>
<!-- Desktop: широкий кроп -->
<img
src="hero-desktop.jpg"
srcset="hero-desktop.jpg 1920w,
hero-desktop-2x.jpg 3840w"
sizes="100vw"
alt="Панорама города"
>
</picture>
Современные форматы с fallback
<picture>
<!-- AVIF -- лучшее сжатие -->
<source type="image/avif" srcset="photo.avif">
<!-- WebP -- хорошее сжатие, широкая поддержка -->
<source type="image/webp" srcset="photo.webp">
<!-- JPEG -- fallback для всех браузеров -->
<img src="photo.jpg" alt="Фото продукта">
</picture>
Комбинация: форматы + адаптивность
<picture>
<!-- AVIF, адаптивный -->
<source
type="image/avif"
srcset="photo-400.avif 400w,
photo-800.avif 800w,
photo-1200.avif 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
>
<!-- WebP, адаптивный -->
<source
type="image/webp"
srcset="photo-400.webp 400w,
photo-800.webp 800w,
photo-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
>
<!-- JPEG fallback -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Фото продукта"
width="800"
height="600"
loading="lazy"
>
</picture>
sizes -- подсказка браузеру
<!-- sizes сообщает: "изображение займёт такую ширину на экране" -->
<img
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"
sizes="
(max-width: 480px) 100vw, /* На мобильных: вся ширина */
(max-width: 1024px) 50vw, /* На планшетах: половина */
(max-width: 1200px) 33vw, /* На десктопах: треть */
400px /* По умолчанию: 400px */
"
src="medium.jpg"
alt="Фото"
>
Важно: sizes -- это подсказка, а не CSS. Браузер не применяет эти размеры к изображению. Реальный размер определяется CSS.
Сравнение форматов
Формат | Размер* | Поддержка | Когда использовать
---------|----------|-----------------|--------------------
AVIF | ~50% | 93%+ (2025) | Когда поддержка есть
WebP | ~70% | 97%+ | Основной выбор
JPEG | 100% | 100% | Fallback
PNG | 150-300% | 100% | Прозрачность (или WebP)
SVG | - | 100% | Иконки, логотипы
* Относительно JPEG при одинаковом качестве
Автоматизация
# Генерация нескольких размеров через sharp-cli
npx sharp-cli resize 400 -i photo.jpg -o photo-400.jpg
npx sharp-cli resize 800 -i photo.jpg -o photo-800.jpg
npx sharp-cli resize 1200 -i photo.jpg -o photo-1200.jpg
# Конвертация в WebP
npx sharp-cli -i photo.jpg -o photo.webp --format webp --quality 80
# Конвертация в AVIF
npx sharp-cli -i photo.jpg -o photo.avif --format avif --quality 60
Частые ошибки
| Ошибка | Проблема | Решение |
|---|---|---|
Нет sizes при w дескрипторах |
Браузер считает 100vw | Указать реальные sizes |
Нет fallback <img> в <picture> |
Ничего не отобразится | <img> обязателен |
Нет alt на <img> |
Недоступно для SR | Добавить описание |
Нет width/height |
Layout shift (CLS) | Указать размеры |
| Слишком много вариантов | Сложность без пользы | 3-4 размера достаточно |
srcset без src |
Старые браузеры не покажут | src как fallback |
Практика
- Создай
<img>сsrcsetи тремя размерами (400w, 800w, 1200w) - Добавь
sizesдля мобильных, планшетов и десктопов - Используй
<picture>для WebP с JPEG fallback - Реализуй art direction: разные кропы для мобильных и десктопов
- Проверь в DevTools (Network tab), какой файл загрузился
Связанные темы
- Изображения -- базовый
<img> - loading lazy -- ленивая загрузка
- viewport -- адаптивный дизайн
- Open Graph и SEO -- изображения для соцсетей