Гайд по использованию тега picture
Тег <picture> — это мощный инструмент для адаптивной подачи изображений в HTML. Он позволяет браузеру выбирать оптимальное изображение в зависимости от характеристик устройства пользователя: размер экрана, плотность пиксельной сетки (Retina), тема оформления и другие медиавыражения. Это критично для оптимизации производительности, особенно для мобильных пользователей.
Основная концепция
Без тега <picture> мы загружаем одно изображение для всех устройств. Если это полноразмерная фотография 2000×1500px, то мобильный пользователь будет загружать этот тяжёлый файл, хотя его экран всего 375px в ширину. Пустая трата трафика и времени.
С помощью <picture> браузер анализирует доступные варианты и загружает только нужный. Мобильник получит оптимизированную версию, а десктоп — полноценное изображение высокого качества.
Синтаксис и структура
<picture>
<source srcset="small.jpg" media="(max-width: 600px)">
<source srcset="medium.jpg" media="(max-width: 1200px)">
<source srcset="large.jpg" media="(min-width: 1201px)">
<img src="large.jpg" alt="Описание изображения">
</picture>Важные правила:
<picture>— контейнер, который сам изображение не выводит<source>— помогает выбрать правильный URL (может быть несколько)<img>— обязателен, именно он отображает картинку (это элемент по умолчанию)- Браузер читает
<source>по порядку и выбирает первый подходящий - Если медиавыражение не сработает и нет подходящих
<source>— используется<img src>
Три основных сценария использования
1. Адаптивность по размеру экрана
Это самый частый случай. Для маленьких экранов мы даём маленькую картинку, для больших — большую.
<picture>
<source srcset="photo-320.jpg" media="(max-width: 480px)">
<source srcset="photo-768.jpg" media="(max-width: 1024px)">
<source srcset="photo-1920.jpg">
<img src="photo-1920.jpg" alt="Панорама горного пейзажа">
</picture>Как это работает:
- Если окно браузера ≤ 480px → загружается
photo-320.jpg - Если окно 481px–1024px → загружается
photo-768.jpg - Если окно > 1024px → загружается
photo-1920.jpg
Экономия трафика:
- Мобильный пользователь (320px): вместо 500KB полноразмерного файла загружает 45KB
- Планшет (768px): вместо 500KB загружает 120KB
- Десктоп (1920px): загружает 500KB для лучшего качества
2. Поддержка высокоплотных дисплеев (Retina)
На MacBook Pro и современных смартфонах плотность пиксельной сетки выше (2x, 3x). Картинка размером 750px на Retina дисплее будет пиксельной. Нужна версия с двойным разрешением.
<picture>
<source srcset="icon-1x.png 1x, icon-2x.png 2x, icon-3x.png 3x">
<img src="icon-1x.png" alt="Иконка профиля">
</picture>Или комбинированный подход:
<picture>
<source
srcset="photo-750.jpg 1x, photo-1500.jpg 2x"
media="(max-width: 800px)">
<source
srcset="photo-1280.jpg 1x, photo-2560.jpg 2x"
media="(min-width: 801px)">
<img src="photo-1280.jpg" alt="Основное изображение">
</picture>Что здесь происходит:
- На обычном мобильном экране (1x): загружается
photo-750.jpg - На iPhone с Retina (2x): загружается
photo-1500.jpg(есть смысл в лучшем качестве) - На десктопе (1x): загружается
photo-1280.jpg - На MacBook Retina (2x): загружается
photo-2560.jpg
3. Адаптация под тёмную тему
Современные браузеры могут определять предпочтения пользователя. Если у него включена тёмная тема — покажем тёмный вариант изображения.
<picture>
<source srcset="logo-dark.png" media="(prefers-color-scheme: dark)">
<img src="logo-light.png" alt="Логотип компании">
</picture>Продвинутые техники
Использование различных форматов изображений
Не все браузеры поддерживают WebP или AVIF. Тогда будем использовать <source> с атрибутом type для подачи разных форматов:
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<source srcset="image.jpg" type="image/jpeg">
<img src="image.jpg" alt="Картинка">
</picture>Приоритет браузера:
- Проверяет поддержку
image/avif→ если поддерживает, загружает AVIF - Если нет → проверяет WebP
- Если нет → берёт JPEG
Это даёт нам огромное преимущество в производительности. AVIF может быть в 2–3 раза меньше, чем JPEG, при том же визуальном качестве.
Комбинированный подход (размер + формат + плотность)
<picture>
<!-- Для мобильных с WebP -->
<source
srcset="hero-mobile.webp 1x, hero-mobile-2x.webp 2x"
media="(max-width: 768px)"
type="image/webp">
<!-- Для мобильных, если нет WebP -->
<source
srcset="hero-mobile.jpg 1x, hero-mobile-2x.jpg 2x"
media="(max-width: 768px)">
<!-- Для десктопа с WebP -->
<source
srcset="hero-desktop.webp 1x, hero-desktop-2x.webp 2x"
type="image/webp">
<!-- Для десктопа, если нет WebP -->
<img
srcset="hero-desktop.jpg 1x, hero-desktop-2x.jpg 2x"
src="hero-desktop.jpg"
alt="Главный баннер сайта">
</picture>Это выглядит сложновато, но браузер справляется без проблем. Мы даём ему несколько вариантов — он выбирает оптимальный.
Стилизация <picture>
Важный момент: сам тег <picture> — это не блочный контейнер, как <div>. Это семантический контейнер. Стили нужно применять к вложенному <img>:
/* Неправильно */
picture {
width: 100%;
max-width: 800px;
}
/* Правильно */
picture img {
width: 100%;
max-width: 800px;
height: auto;
display: block;
}Если нужно задать класс для большего контроля:
<picture class="hero-image">
<source srcset="hero-mobile.webp" media="(max-width: 768px)">
<img src="hero-desktop.jpg" alt="Заголовок">
</picture>.hero-image img {
width: 100%;
height: auto;
object-fit: cover;
object-position: center;
}Частые ошибки
❌ Ошибка 1: Забытый <img>
<!-- Браузер ничего не покажет! -->
<picture>
<source srcset="image.jpg" media="(max-width: 768px)">
</picture>Тег <img> нужен всегда. Он — якорь, который гарантирует, что картинка появится.
❌ Ошибка 2: Стили на <picture> вместо <img>
/* Не работает так, как ожидаем */
picture {
width: 100%;
border-radius: 8px;
}/* Правильно */
picture img {
width: 100%;
border-radius: 8px;
}❌ Ошибка 3: Неправильный порядок <source>
<!-- Неправильно: от общего к частному -->
<picture>
<source srcset="large.jpg">
<source srcset="small.jpg" media="(max-width: 600px)">
<img src="large.jpg" alt="">
</picture>Браузер выберет первый подходящий. Если large.jpg без медиавыражения — он всегда подходит. Правильный порядок:
<!-- Правильно: от частного к общему -->
<picture>
<source srcset="small.jpg" media="(max-width: 600px)">
<source srcset="medium.jpg" media="(max-width: 1200px)">
<source srcset="large.jpg">
<img src="large.jpg" alt="">
</picture>Практические советы веб-разработчику
- Автоматизация генерации версий изображений — используй инструменты типа ImageMagick, Sharp (Node.js) или онлайн-сервисы для создания нескольких версий. Вручную это делать утомительно.
- Правильный alt-текст — добавляй его в
<img>, он критичен для SEO и доступности. На<source>alt не добавляется. - Проверка поддержки браузером —
<picture>поддерживается во всех современных браузерах (IE 11 и старше — не поддерживают, но это уже древность). - Инструменты для оптимизации:
- TinyPNG/TinyJPG — сжатие
- Squoosh (Google) — конвертация в WebP/AVIF
- ImageOptim (Mac) — пакетное сжатие
- На продакшене — рассмотри использование Image CDN (Cloudinary, Imgix), которые автоматически подают правильные размеры и форматы в зависимости от User-Agent браузера.
Реальный пример: адаптивное изображение для статьи
<picture class="article-hero">
<!-- Мобильные устройства, WebP -->
<source
srcset="article-hero-480w.webp 1x, article-hero-960w.webp 2x"
media="(max-width: 640px)"
type="image/webp">
<!-- Мобильные устройства, fallback JPEG -->
<source
srcset="article-hero-480w.jpg 1x, article-hero-960w.jpg 2x"
media="(max-width: 640px)">
<!-- Планшеты, WebP -->
<source
srcset="article-hero-800w.webp 1x, article-hero-1600w.webp 2x"
media="(max-width: 1024px)"
type="image/webp">
<!-- Планшеты, fallback JPEG -->
<source
srcset="article-hero-800w.jpg 1x, article-hero-1600w.jpg 2x"
media="(max-width: 1024px)">
<!-- Десктоп, WebP -->
<source
srcset="article-hero-1200w.webp 1x, article-hero-2400w.webp 2x"
type="image/webp">
<!-- Десктоп, fallback JPEG -->
<img
srcset="article-hero-1200w.jpg 1x, article-hero-2400w.jpg 2x"
src="article-hero-1200w.jpg"
alt="Стена с граффити — иллюстрация к статье о уличном искусстве">
</picture>.article-hero img {
width: 100%;
height: auto;
display: block;
max-width: 1200px;
}Этот пример охватывает все случаи: разные размеры экрана, плотность дисплея и форматы изображений. Браузер выберет оптимальное.