Тег picture (от английского picture, «картинка») помогает браузеру выбрать, какой именно файл показать: файл другого формата, другой кадр или версию для тёмной темы. Сам он ничего не рисует и служит контейнером: внутри записывают один или несколько тегов source с условиями, а в конце обязательный img. Тег парный, закрывающий тег обязателен.
Работает это без скриптов: браузер проверяет условия по порядку и берёт первый подходящий файл. Чаще всего picture нужен в двух случаях: подать современный формат (AVIF или WebP) с запасным JPEG либо показать на узком экране другой кадр, а не уменьшенную копию. Если картинка просто масштабируется под ширину, picture не нужен, хватит img. Сам img разобран на странице о теге img, поэтому здесь о нём только то, что связано с picture.
<picture>
<source srcset="kot-wide.jpg" media="(min-width: 600px)">
<img src="kot-narrow.jpg" alt="Горы под солнцем"
width="300" height="375">
</picture>
В этой статье
- Тег picture в HTML: что это и какие у него атрибуты
- Как тег picture выбирает картинку: source по порядку
- Атрибут type у source в picture: WebP и AVIF с запасным JPEG
- Атрибут media у source в picture: разные картинки для экрана, тёмной темы и печати
- Тег picture или img: чем отличаются и когда нужен каждый
- Что задаётся у img внутри picture: alt, width, height, loading
- Стили тега picture в CSS: размеры, выравнивание, object-fit
- Поддержка тега picture браузерами и как проверить выбор
Тег picture в HTML: что это и какие у него атрибуты
Сначала о том, из чего состоит тег и какие настройки у него есть.
Тег picture ничего не выводит сам: он только создаёт контекст для вложенного img. По стандарту внутри записывают ноль или несколько source, а после них ровно один img. Без img на странице ничего не появится: в примере ниже видно, что блок получается нулевого размера. Собственных атрибутов у picture нет, только глобальные (class, id, title, lang и другие). Поэтому настройки задаются не у него, а у вложенных тегов: условия у source, а описание и размер у img.
<picture>
<source srcset="kot.webp" media="(min-width: 1px)">
<img src="kot.jpg" alt="Горы">
</picture>
<picture>
<source srcset="kot.webp">
</picture>
<img src="kot.jpg" alt="Горы">
Пример: что выводит picture с img и без него
Переключайте кнопки. Файлы в примере встроенные, надпись на картинке показывает, какой из них выбран.
Записывать picture можно везде, где допустимо встраиваемое содержимое: в абзаце, в ссылке, в кнопке, в figure. По умолчанию это строчный элемент, как и сам img, подробнее об этом в разделе про стили.
Как тег picture выбирает картинку: source по порядку
Выбор происходит по простому правилу, и порядок записи тегов в нём решает всё.
Браузер просматривает source сверху вниз и берёт первый, у которого выполняются все условия (media и type). Остальные он не смотрит, даже если они тоже подходят. Если подходящих нет, показывается файл из img. Поэтому img всегда записывают последним: все source после него браузер игнорирует.
<picture>
<source srcset="a.jpg">
<source srcset="b.jpg">
<img src="fallback.jpg" alt="Горы">
</picture>
Пример: как порядок source влияет на результат
Четыре порядка записи. Структура собирается из настоящих тегов, а название выбранного файла совпадает с надписью на картинке.
Есть три особенности. Тег source без srcset (с одним src) браузер пропускает: для picture нужен именно srcset. Если source подошёл, атрибуты src и srcset у img уже не используются. И самое неприятное: если файл выбранного source не найден, браузер к img не возвращается. В Chrome после выбора адрес запасного файла не применяется, и вместо картинки будет сбой загрузки. Запасной img защищает от неподдерживаемых условий, а не от опечатки в пути.
Атрибут type у source в picture: WebP и AVIF с запасным JPEG
По атрибуту type браузер узнаёт формат файла и пропускает те, которые не умеет показывать.
Атрибут type у source содержит MIME-тип файла. Браузер не загружает файл для проверки, он смотрит только на этот тип: если формат ему незнаком, source пропускается и проверяется следующий. Поэтому форматы записывают от новых к старым: сначала AVIF, затем WebP, а в самом img обычный JPEG. Если type не указать, source считается подходящим всегда, и браузер, не умеющий читать этот формат, получит сбой без запасного варианта.
<picture>
<source srcset="kot.avif" type="image/avif">
<source srcset="kot.webp" type="image/webp">
<img src="kot.jpg" alt="Горы под солнцем">
</picture>
Пример: какие значения type принимает ваш браузер
Таблица заполняется при открытии страницы настоящими тегами picture в вашем браузере, поэтому результат отражает именно его.
Тип для JPEG пишется image/jpeg. Запись image/jpg Chrome понимает, но она не стандартная, и рассчитывать на неё не стоит. AVIF и WebP сегодня читают все актуальные браузеры, поэтому запасной вариант для них нужен только очень старым версиям, а нужен ли он вашей аудитории, решать вам.
| Формат | Значение type | Пример записи |
|---|---|---|
| AVIF | image/avif | srcset="kot.avif" type="image/avif" |
| WebP | image/webp | srcset="kot.webp" type="image/webp" |
| JPEG | image/jpeg | srcset="kot.jpg" type="image/jpeg" |
| PNG | image/png | srcset="kot.png" type="image/png" |
| SVG | image/svg+xml | srcset="kot.svg" type="image/svg+xml" |
| GIF | image/gif | srcset="kot.gif" type="image/gif" |
Атрибут media у source в picture: разные картинки для экрана, тёмной темы и печати
Условие в media позволяет показывать разные кадры, а не просто разные размеры.
Значение media записывается так же, как условие в CSS, и проверяется на ширине окна браузера, а не на блоке, в котором находится картинка. Блок вокруг картинки на выбор никак не влияет. Когда окно меняет ширину, браузер переключает файл на ходу, страницу перезагружать не нужно. Такой приём называют художественной подачей: на широком экране показывают панораму, на узком обрезанный кадр с главным объектом.
<picture>
<source srcset="wide.jpg" media="(min-width: 200px)">
<img src="narrow.jpg" alt="Горы под солнцем">
</picture>
Пример: выбор по ширине окна
Двигайте ползунок. Внутри рамки отдельное окно с настоящим picture, а красной линией обведён блок шириной 96 px, в котором стоит картинка.
Кроме ширины в media можно проверить ориентацию, плотность экрана, предпочтение тёмной темы или меньшего движения, а также печать. Условие обязательно записывается в скобках: запись без них, например min-width:600px, браузер не считает подходящей и пропускает source.
<picture>
<source srcset="night.jpg"
media="(prefers-color-scheme: dark)">
<img src="day.jpg" alt="Горы под солнцем">
</picture>
Пример: выбор по теме браузера
Пример показывает выбор для вашей текущей темы. Чтобы увидеть другой вариант, смените тему в настройках системы или браузера и обновите страницу.
Условие в media | Когда source подходит | Пример записи |
|---|---|---|
(min-width: 600px) | Окно шириной от 600 px | srcset="wide.jpg" media="(min-width: 600px)" |
(orientation: landscape) | Ширина окна больше высоты | srcset="wide.jpg" media="(orientation: landscape)" |
(min-resolution: 2dppx) | Экран с плотностью пикселей от 2x | srcset="kot-2x.jpg" media="(min-resolution: 2dppx)" |
(prefers-color-scheme: dark) | Включена тёмная тема | srcset="night.jpg" media="(prefers-color-scheme: dark)" |
(prefers-reduced-motion: reduce) | Пользователь просит меньше движения: можно дать статичную картинку вместо анимированной | srcset="still.webp" media="(prefers-reduced-motion: reduce)" |
print | Страница выводится на печать | srcset="print.png" media="print" |
Тег picture или img: чем отличаются и когда нужен каждый
Выбирать между picture и img нужно по задаче, и в большинстве случаев хватает одного img.
Различие в строгости. Атрибуты srcset и sizes у img работают как подсказка: браузер сам решает, какой из файлов взять. Теги source с media и type работают как команда: первый подходящий файл обязательно выбирается. Если кадр один и меняется только размер файла, достаточно img со srcset. Если нужен другой кадр или формат, подбираемый по возможностям браузера, нужен picture. Внутри него img остаётся обязательным, и поэтому picture не заменяет img, а дополняет его.
<img src="kot-800.jpg"
srcset="kot-800.jpg 800w, kot-1600.jpg 1600w"
sizes="100vw" alt="Горы под солнцем">
Пример: какой тег выбрать для задачи
Четыре задачи. Для каждой приведён подходящий код и настоящий результат, а под кнопками объяснено, почему выбран именно этот тег.
| Задача | Что взять | Пример записи |
|---|---|---|
| Одна картинка без условий | img | src="kot.jpg" alt="Горы" |
| Один кадр, разный размер файла | img со srcset и sizes | srcset="a.jpg 800w, b.jpg 1600w" sizes="100vw" |
| Другой кадр на узком экране | picture и media | srcset="wide.jpg" media="(min-width: 600px)" |
| Современный формат с запасным | picture и type | srcset="kot.avif" type="image/avif" |
| Картинка для тёмной темы | picture и media | srcset="night.jpg" media="(prefers-color-scheme: dark)" |
Что задаётся у img внутри picture: alt, width, height, loading
Почти всё, что описывает картинку, по-прежнему записывается у img, а не у picture и source.
Описание alt существует только у img, у picture и source такого атрибута нет. Описание одно на все варианты, поэтому оно должно подходить и панораме, и узкому кадру. Атрибуты loading, decoding, fetchpriority тоже относятся к img. Подробно о них рассказано на странице о теге img.
Размеры устроены тоньше. У source можно записать собственные width и height. Браузер берёт их у выбранного source и по ним резервирует место, пока файл загружается. Это важно для художественной подачи, когда у кадров разные пропорции: размеры только у img подходят лишь одному из них.
<picture>
<source srcset="wide.jpg" media="(min-width: 600px)"
width="600" height="200">
<img src="narrow.jpg" alt="Горы под солнцем"
width="300" height="375" loading="lazy">
</picture>
Пример: чьи размеры использует браузер
Четыре варианта размеров. У созданной картинки читается соотношение сторон, а зелёный прямоугольник показывает, какое место браузер зарезервирует до загрузки файла.
Стили тега picture в CSS: размеры, выравнивание, object-fit
Картинка в picture оформляется как обычная, но размеры и зазор задают у img, а не у picture.
Тег picture по умолчанию строчный, поэтому ширина и высота на нём не работают, а высота его рамки зависит от шрифта, а не от картинки. Пока он строчный, его width игнорируется, а после display: block блок сужается, но картинка внутри остаётся прежней и выходит за его границы. Зазор под картинкой, о котором рассказано на странице о img, никуда не пропадает, и display: block у picture его не убирает: нужно записать display: block у вложенного img. Поэтому стили размеров, скругления и object-fit пишут для picture img.
picture img {
display: block;
max-width: 100%;
height: auto;
}
Пример: где применять размер и display
Включайте правила по одному. Пунктиром обведён picture, а под картинкой написано, какой размер получил каждый из них и остался ли зазор.
| Задача | Где записать | Пример записи |
|---|---|---|
| Размер картинки | У img | width: 100%; height: auto; |
| Убрать зазор под картинкой | У img | display: block; |
Скругление, рамка, object-fit | У img | border-radius: 12px; object-fit: cover; |
| Центрирование по горизонтали | У img: блок и автоотступы | display: block; margin: 0 auto; |
| Скрыть картинку | У picture (скрывается вместе с вложенными) | display: none; |
Поддержка тега picture браузерами и как проверить выбор
Поддержка у тега полная, а в браузерах без неё страница не ломается.
Тег picture работает во всех актуальных браузерах и считается стабильным с марта 2016 года. Браузер, который его не знает, игнорирует незнакомые picture и source и показывает вложенный img. Именно поэтому img обязателен: он служит и основным, и запасным вариантом. Для поисковых систем действует то же правило: в документации Google для картинок рекомендуют всегда записывать запасной img с атрибутом src.
if ("HTMLPictureElement" in window) {
const img = document.querySelector("picture img");
console.log(img.currentSrc);
}
Пример: проверка поддержки и выбранного файла
Кнопка создаёт настоящий picture заново и читает у него объект поддержки и свойство currentSrc.
Свойство currentSrc у img показывает адрес файла, который браузер выбрал сейчас, даже если выбор сделал source. Если нужно узнать, какой файл реально загрузился, посмотрите вкладку «Сеть» в инструментах разработчика.
Частые ошибки с тегом picture
Почти все промахи с picture сводятся к порядку тегов, условиям и месту, где записаны размеры.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
<picture><source ...></picture> | Нет img: на странице ничего не появляется | Последним записать img с src и alt |
<img ...><source ...> | source записан после img и игнорируется | Все source записать до img |
<source src="kot.webp"> | Нет srcset: source пропускается | Написать srcset="kot.webp" |
source с новым форматом без type | Браузер, не знающий формат, всё равно выберет его и получит сбой без запасного | Добавить type="image/avif" |
Опечатка в пути у source | Выбранный source не загрузился, а запасной img не используется | Проверить путь, открыв адрес картинки отдельно |
media="min-width:600px" | Нет скобок: условие не подходит, source пропускается | Написать media="(min-width: 600px)" |
Ожидание, что media проверяет блок | Проверяется ширина окна, а не блока, в котором стоит картинка | Строить условия от ширины окна |
<source alt="Горы"> | У source и picture нет alt, атрибут не действует | Записать alt у img |
picture { width: 300px; } | У строчного picture ширина не работает, картинка не меняется | Задать размер у картинки: picture img { width: 300px; } |
Скрипт меняет img.src | Пока source подходит, картинка не меняется | Менять srcset у source или убрать source |
Размеры только у img при разных кадрах | Для другого кадра резерв места неверный, страница сдвигается | Записать width и height у каждого source |
type="image/jpg" | Chrome поймёт, но такого типа не существует | Писать type="image/jpeg" |