Тег picture в HTML: что это и как работает с img и source

Тег picture (от английского picture, «картинка») помогает браузеру выбрать, какой именно файл показать: файл другого формата, другой кадр или версию для тёмной темы. Сам он ничего не рисует и служит контейнером: внутри записывают один или несколько тегов source с условиями, а в конце обязательный img. Тег парный, закрывающий тег обязателен.

Работает это без скриптов: браузер проверяет условия по порядку и берёт первый подходящий файл. Чаще всего picture нужен в двух случаях: подать современный формат (AVIF или WebP) с запасным JPEG либо показать на узком экране другой кадр, а не уменьшенную копию. Если картинка просто масштабируется под ширину, picture не нужен, хватит img. Сам img разобран на странице о теге img, поэтому здесь о нём только то, что связано с picture.

HTML
<picture>
  <source srcset="kot-wide.jpg" media="(min-width: 600px)">
  <img src="kot-narrow.jpg" alt="Горы под солнцем"
       width="300" height="375">
</picture>

Тег picture в HTML: что это и какие у него атрибуты

Сначала о том, из чего состоит тег и какие настройки у него есть.

Тег picture ничего не выводит сам: он только создаёт контекст для вложенного img. По стандарту внутри записывают ноль или несколько source, а после них ровно один img. Без img на странице ничего не появится: в примере ниже видно, что блок получается нулевого размера. Собственных атрибутов у picture нет, только глобальные (class, id, title, lang и другие). Поэтому настройки задаются не у него, а у вложенных тегов: условия у source, а описание и размер у img.

HTML
<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 после него браузер игнорирует.

HTML
<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 считается подходящим всегда, и браузер, не умеющий читать этот формат, получит сбой без запасного варианта.

HTML
<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Пример записи
AVIFimage/avifsrcset="kot.avif" type="image/avif"
WebPimage/webpsrcset="kot.webp" type="image/webp"
JPEGimage/jpegsrcset="kot.jpg" type="image/jpeg"
PNGimage/pngsrcset="kot.png" type="image/png"
SVGimage/svg+xmlsrcset="kot.svg" type="image/svg+xml"
GIFimage/gifsrcset="kot.gif" type="image/gif"

Атрибут media у source в picture: разные картинки для экрана, тёмной темы и печати

Условие в media позволяет показывать разные кадры, а не просто разные размеры.

Значение media записывается так же, как условие в CSS, и проверяется на ширине окна браузера, а не на блоке, в котором находится картинка. Блок вокруг картинки на выбор никак не влияет. Когда окно меняет ширину, браузер переключает файл на ходу, страницу перезагружать не нужно. Такой приём называют художественной подачей: на широком экране показывают панораму, на узком обрезанный кадр с главным объектом.

HTML
<picture>
  <source srcset="wide.jpg" media="(min-width: 200px)">
  <img src="narrow.jpg" alt="Горы под солнцем">
</picture>

Пример: выбор по ширине окна

Результат

Двигайте ползунок. Внутри рамки отдельное окно с настоящим picture, а красной линией обведён блок шириной 96 px, в котором стоит картинка.

Кроме ширины в media можно проверить ориентацию, плотность экрана, предпочтение тёмной темы или меньшего движения, а также печать. Условие обязательно записывается в скобках: запись без них, например min-width:600px, браузер не считает подходящей и пропускает source.

HTML
<picture>
  <source srcset="night.jpg"
          media="(prefers-color-scheme: dark)">
  <img src="day.jpg" alt="Горы под солнцем">
</picture>

Пример: выбор по теме браузера

Результат

Пример показывает выбор для вашей текущей темы. Чтобы увидеть другой вариант, смените тему в настройках системы или браузера и обновите страницу.

Условие в mediaКогда source подходитПример записи
(min-width: 600px)Окно шириной от 600 pxsrcset="wide.jpg" media="(min-width: 600px)"
(orientation: landscape)Ширина окна больше высотыsrcset="wide.jpg" media="(orientation: landscape)"
(min-resolution: 2dppx)Экран с плотностью пикселей от 2xsrcset="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, а дополняет его.

HTML
<img src="kot-800.jpg"
     srcset="kot-800.jpg 800w, kot-1600.jpg 1600w"
     sizes="100vw" alt="Горы под солнцем">

Пример: какой тег выбрать для задачи

Результат

Четыре задачи. Для каждой приведён подходящий код и настоящий результат, а под кнопками объяснено, почему выбран именно этот тег.

ЗадачаЧто взятьПример записи
Одна картинка без условийimgsrc="kot.jpg" alt="Горы"
Один кадр, разный размер файлаimg со srcset и sizessrcset="a.jpg 800w, b.jpg 1600w" sizes="100vw"
Другой кадр на узком экранеpicture и mediasrcset="wide.jpg" media="(min-width: 600px)"
Современный формат с запаснымpicture и typesrcset="kot.avif" type="image/avif"
Картинка для тёмной темыpicture и mediasrcset="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 подходят лишь одному из них.

HTML
<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.

CSS
picture img {
  display: block;
  max-width: 100%;
  height: auto;
}

Пример: где применять размер и display

Результат

Включайте правила по одному. Пунктиром обведён picture, а под картинкой написано, какой размер получил каждый из них и остался ли зазор.

ЗадачаГде записатьПример записи
Размер картинкиУ imgwidth: 100%; height: auto;
Убрать зазор под картинкойУ imgdisplay: block;
Скругление, рамка, object-fitУ imgborder-radius: 12px; object-fit: cover;
Центрирование по горизонталиУ img: блок и автоотступыdisplay: block; margin: 0 auto;
Скрыть картинкуУ picture (скрывается вместе с вложенными)display: none;

Поддержка тега picture браузерами и как проверить выбор

Поддержка у тега полная, а в браузерах без неё страница не ломается.

Тег picture работает во всех актуальных браузерах и считается стабильным с марта 2016 года. Браузер, который его не знает, игнорирует незнакомые picture и source и показывает вложенный img. Именно поэтому img обязателен: он служит и основным, и запасным вариантом. Для поисковых систем действует то же правило: в документации Google для картинок рекомендуют всегда записывать запасной img с атрибутом src.

JavaScript
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"
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×