Теги img
и picture
предназначены для загрузки изображений. Каждый из них позволяет задать набор правил, согласно которым браузер будет выбирать, какое из изображений загружать. Рассмотрим синтаксис и различия данных тегов. Для начала нужно задать следующий метатег:
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
Данный метатег указывает браузеру выполнять масштабирование размеров экрана устройства. Так, например, размеры экрана iPhone X составляют 375x812 css-пикселей.
Для тестирования будем использовать следующее изображение:
Тег img
Атрибут srcset
предназначен для указания всех доступных размеров изображений и URL каждого из них. При этом, тег src
указывать нужно. Его значение будет использовано, если все варианты из srcset
не подойдут согласно указанным правилам.
Атрибут srcset
содержит список из одной или нескольких строк, разделённых запятыми, указывающих набор источников изображения. Каждая строка состоит из:
URL изображения.
Дескриптора ширины.
Рассмотрим на примере:
<img
src="bears-1920x1080.jpg"
alt="bears"
srcset="
bears-480x270.jpg 480w,
bears-960x540.jpg 960w,
bears-1920x1080.jpg 1920w
"
/>
Ширина всех доступных изображений указывается в пикселях. По историческим причинам для обозначения пикселей используется символ w
. В данном примере атрибут srcset
содержит три изображения, ширина которых 480, 960 и 1920 пикселей соответственно. Браузер выберет изображение в зависимости от ширины экрана устройтва и его плотности пикселей. Если ширина экрана не превышает 480 css-пикселей, то будет выбрано следующее изображение:
bears-480x270.jpg
, если коэфициент плотности пикселей равен 1.bears-960x540.jpg
, если коэфициент плотности пикселей равен 2 (retina display).bears-1920x1080.jpg
, если коэфициент плотности пикселей больше 2.
Аналогично, если ширина экрана больше 480 css-пикселей, но не превышает 960 css-пикселей, то:
bears-960x540.jpg
, если коэфициент плотности пикселей равен 1.bears-1920x1080.jpg
, если коэфициент плотности пикселей больше или равен 2.
При этом браузер будет подразумевать, что изображение занимает всю ширину экрана. Для переопределения такого поведения предназначен атрибут sizes
, который содержит список из одной или нескольких строк, разделённых запятыми, указывающих какую максимальную ширину может занимать изображение при определённом размере экрана. Каждая строка состоит из:
Ширины изображения.
Рассмотрим на примере:
<img
src="bears-1920x1080.jpg"
alt="bears"
sizes="(max-width: 600px) 480px, (max-width: 1200px) 960px, 100vw"
srcset="
bears-480x270.jpg 480w,
bears-960x540.jpg 960w,
bears-1920x1080.jpg 1920w
"
/>
В данном примере браузер будет следовать следующим правилам при выборе источника изображения:
Если ширина экрана устройства составляет не более 600 css-пикселей, то изображение на таком экране занимает максимум 480 css-пикселей в ширину.
Если ширина экрана устройства составляет от 600 до 1200 css-пикселей, то изображение на таком экране занимает максимум 960 css-пикселей в ширину.
В противном случае браузер будет подразумевать, что изображение может занимает всю ширину экрана.
Также нужно учитывать коэфициент плотности пикселей. Например, если ширина экрана устройства составляет 550 css-пикселей, то браузер выберет следующее изображение:
bears-480x270.jpg
, если коэфициент плотности пикселей равен 1. Так как ширина экрана устройства не превышает 600 css-пикселей, то изображение на таком экране занимает максимум 480 css-пикселей в ширину.bears-960x540.jpg
, если коэфициент плотности пикселей равен 2.bears-1920x1080.jpg
, если коэфициент плотности пикселей больше 2.
Атрибут sizes
нужно указывать, если размеры изображения ограничены css стилями. Если атрибут sizes
не указан, то по умолчанию он будет иметь значение 100vw
(sizes="100vw"
), то есть браузер будет подразумевать, что изображение может занимает всю ширину экрана.
Тег picture
Тег picture
служит контейнером для одного или более тегов source
и одного тега img
. Тег source
представляет собой источник изображения. Он содержит информацию о формате изображения и его размерах, а также правила, при соблюдении которых браузер должен выбрать этот источник. Если все источники не подходят, то будет выбран файл, указанный в атрибуте src
тега img
. Если сразу несколько источников подходят, то браузер выберет первый по порядку.
Тег source
имеет атрибуты sizes
и srcset
. Они работают также, как и соотвествующие атрибуты у тега img
. Рассмотрим на примере:
<picture>
<source
srcset="bears-480x270.jpg 480w, bears-960x540.jpg 960w, bears-1920x1080.jpg 1920w"
sizes="(max-width: 600px) 480px, (max-width: 1200px) 960px, 100vw"
/>
<img src="bears-1920x1080.jpg" alt="bears" />
</picture>
Данный пример работает так же, как и второй пример использования тега img
.
Разница между img и picture
Тег picture
позволяет указать браузеру использовать разные изображения в зависимости от размера экрана. Достигается это за счёт использования атрибута media
тега source
, который позволяет задать медиа выражение, при котором будет использоваться данный источник. Например, на маленьких экранах мы хотим использовать обрезанное изображение cropped-bears.jpg
, которое содержит основную часть изображения:
Для этого нужно указать несколько тегов source
и задать им атрибуты media
:
<picture>
<source
media="(max-width: 480px)"
srcset="
cropped-bears-480x270.jpg 480w,
cropped-bears-960x540.jpg 960w
"
/>
<source
media="(max-width: 960px)"
srcset="bears-960x540.jpg 960w, bears-1920x1080.jpg 1920w"
/>
<img src="bears-1920x1080.jpg" alt="bears" />
</picture>
В данном примере, если ширина экрана устройства не превышает 480 css-пикселей, то будет выбрано обрезанное изображение. Добиться такого результата при помощи тега img
не получиться, так как изображения cropped-bears-960x540.jpg
и bears-960x540.jpg
имеют одинаковый размер, но изображение cropped-bears-960x540.jpg
предназначено для использования на устройстве, ширина которого не превышает 480 css-пикселей и коэфициент протности пикселей равен 2, а изображение bears-960x540.jpg
- на устройстве, ширина которого от 480 до 960 css-пикселей и коэфициент протности пикселей равен 1.
Также, тег picture
позволяет указать различные форматы изображения, например webp
и jpeg
. Для этого нужно тегу source
задать атрибут type:
<picture>
<source
type="image/webp"
media="(max-width: 480px)"
srcset="
cropped-bears-480x270.webp 480w,
cropped-bears-960x540.webp 960w
"
/>
<source
type="image/webp"
media="(max-width: 960px)"
srcset="bears-960x540.webp 960w, bears-1920x1080.webp 1920w"
/>
<source
type="image/jpeg"
media="(max-width: 480px)"
srcset="
cropped-bears-480x270.jpg 480w,
cropped-bears-960x540.jpg 960w
"
/>
<source
type="image/jpeg"
media="(max-width: 960px)"
srcset="bears-960x540.jpg 960w, bears-1920x1080.jpg 1920w"
/>
<img src="bears-1920x1080.jpg" alt="bears" />
</picture>
Источники с наименее поддерживаемыми типами нужно располагать в начале списка, так как браузер выберет первый по порядку подходящий источник. В данном примере браузер выберет тип изображения webp
, если он его поддерживает. В противном случае будет выбран тип jpeg
.
Комментарии (11)
ivan386
11.08.2021 20:27+1Я поэкспериментировал в Firefox и получил следующие результаты:
При отсутствии sizes браузер выбирает первое изображение которое шире окна.
При наличии sizes браузер выбирает изображение шире заданного размера.
<img src="bears-1920x1080.jpg" alt="bears" sizes="(max-width: 600px) 480px, (max-width: 1200px) 960px, 100vw" srcset=" bears-480x270.jpg 480w, bears-960x540.jpg 960w, bears-1920x1080.jpg 1920w " />
Тобиж по крайней мере в Firefox картинка bears-480x270.jpg в этом примере не будет показана никогда.
Makito
27.08.2021 14:27Заметил такую странность - если изменять ширину окна, пройдя через все описанные в sizes брекпойнты, то браузер сначала выбирает изображения согласно описанным правилам, но в итоге найдет максимальную ширину изображения из sizes и будет применять только эту ширину изображения, игнорируя дальнейшие изменения ширины окна. То есть правила брекпойнтов из sizes перестают действовать.
Хотя в спецификации о таком поведении нигде не написано.
ivan386
28.08.2021 03:39В каком браузере такое поведение? В Firefox 91.0.2 у меня при сужении окна браузер выбирает картинку меньше.
Makito
28.08.2021 10:04Хром 92. А вы после сужения снова расширьте, пройдитесь несколько раз по всем брекпойнтам без перезагрузки страницы, и посмотрите какой размер картинки берется для рендера.
ivan386
28.08.2021 16:18Вот я выше делал тестовую страницу. Сколько я бы её не менял по ширине туда и обратно Firefox меняет изображения согласно заданному sizes.
Makito
28.08.2021 21:01Проверил - фокс ведет себя адекватно, а вот хром всегда выдает изображение 1920w. И еще странность - если просто изменять размер окна, то медиазапрос он отображает верно, а если включить режим эмуляции мобильного устройства и там изменять ширину области, то медиа ниже 1200 он тоже не отрабатывает.
В общем с хромом что то неладно.
mistergrim
Как уничтожить веб, серия №-я.