HTML атрибуты: srcset, sizes и тег <picture>
Проблема адаптивных (отзывчивых) изображений будоражит умы веб-разработчиков уже давно. Это задача, когда нужно показывать большую картинку на больших экранах и маленькую на маленьких. Такая проблема решается через HTML атрибуты srcset
и sizes
, а также тег <picture>
. Ниже рассмотрим их подробнее.
HTML атрибуты srcset и sizes
srcset
srcset
— это замена атрибутаsrc
- он приоритетнее чем src!- src атрибут должен быть всегда указан! Это нужно для поисковых роботов.
- src будет использован, только если браузер не поддерживает srcset.
- Firefox и Chrome обрабатывают srcset чуть-чуть по-разному, но общая логика сохраняется. Firefox например может понижать размер картики при уменьшении ширины экрана, а Chrome если загрузил больший размер, то будет использовать его и на меньших разрешениях. Просчет какую картинку выбрать также чуть-чуть отличается.
srcset — содержит сет УРЛов на картинки (через запятую), чтобы браузер мог выбрать наиболее подходящий вариант в зависимости от параметров экрана устройства, с которого просматривается страница.
В srcset
можно указать один или несколько URL.
В srcset
подразумевается указывать разные размеры одной и той же картинки. Можно указать и разные, но логика его работы подразумевает одну и ту же картинку.
Каждая строка в списке должна содержать УРЛ и дескриптор. Если никакой дескриптор не указан, то берется по умолчанию - 1x
.
Дескриптор может быть двух типов:
Физическая ширина картинки
в пикселях (actual width). Например600w
,1000w
.Плотность пикселей устройства
(display density) - DPR (device pixel ratio), например2x
,3x
.
Ваш текущий DPR можно узнать в консоли баразура, заглянув в переменную window.devicePixelRatio
.
Дискриптор нужен браузеру, чтобы он мог принять решение какой УРЛ из сета загружать (ведь он заранее ничего не знает о картинке которая находится в УРЛ). А с дескриптором, браузер заранее понимает какая у картинки ширина или для какого DPR она подходит.
Синтаксис srcset имеет следующий вид:
<img srcset="image-1200.jpg" src="full.jpg"> <img srcset="image-640.jpg 640w, image-960.jpg 960w, image-1200.jpg 1200w" src="full.jpg"> <img srcset="image-640.jpg, image-1280.jpg 2x, image-1920.jpg 3x" src="full.jpg">
Как это работает на примере:
<img srcset="image-640.jpg 640w, image-960.jpg 960w, image-1200.jpg 1200w" src="full.jpg">
В этом примере картинка full.jpg
не будет использоваться, потому что есть атрибут srcset - браузер выберет наиболее подходящее изображение из srcset.
Какую картинку выберет барузер?
-
Если у вашего устройства DPR=1:
image-640.jpg
- если ширина экрана > 0px и <= 640px.image-960.jpg
- если ширина экрана > 640px и <= 960px.image-1200.jpg
- если ширина экрана > 960px.
- Если у вашего устройства DPR=2 (подходящая картинка будет в 2 раза больше её физической ширины):
image-640.jpg
- если ширина экрана > 0px и <= 320px (640/2).image-960.jpg
- если ширина экрана > 320px и <= 480px (960/2).image-1200.jpg
- если ширина экрана > 480px.
Как это работает на примере:
<img srcset="image-640.jpg, image-1280.jpg 2x, image-1920.jpg 3x" src="full.jpg">
Какую картинку выберет барузер?
image-640.jpg
- если DPR устройства = 1.image-1280.jpg
- если DPR устройства = 2.image-1920.jpg
- если DPR устройства = 3.
На самсунгах и других телефонах, часто DPR доходит до 4!
Примеры поиграться:
- https://miliutin.ru/tests/srcset/2.html (без sizes)
- https://miliutin.ru/tests/srcset/1.html (с sizes)
- https://miliutin.ru/tests/srcset/4.html (с атрибутом sizes)
- https://imagekitio.github.io/responsive-images-guide/srcset-density.html (DPR)
sizes + srcset
Когда изображение занимает лишь часть ширины экрана. srcset без sizes будет недостаточно.
Поскольку браузер ничего не знает о лейоуте (как выглядит страница), он будет считать, что картинка занимает всю ширину экрана. Но если картинка занимает лишь часть, то в результате будет загружено большее чем нужно изображение.
Так стоп! Что? Браузер не знает о лейоуте?
Логично предположить, что у браузера есть css стили и он может узнать какая ширина в итоге будет у картинки! Но, на момент парсинга тега IMG css стили еще не интерпертированы, макет (лейоут) еще не нарисован! Если браузер будет ждать, пока все таблицы стилей будут разобраны и выполнены, это приведет к задержке загрузки изображений.
Если для картинки не указаны никакие размеры в css, то sizes также ограничит размер картинки, как это делает атрибут width.
И если для картинки указать, например, css свойство: max-width:100%
, то это свойство перебивает значение атрибута sizes: т.е. если ширина картинки по sizes больше ширины элемента в котором она расположена - её ширина будет равна ширине элемента (max-width:100%). В общем, все также как и для стандартных width и height атрибутов. Но повторюсь еще раз - sizes нужен браузеру - это дополнение к атрибуту srcset.
sizes
содержит список элементов (через запятую), где каждый элемент описывает размер изображения по отношению к ширине экрана (области просмотра).
Использование sizes дает браузеру дополнительную информацию, чтобы правильно выбрать подходящую картинку из srcset и начать её загрузку, как только он увидит тег <img>, не дожидаясь, парсинга css стилей.
Синтаксис:
<img srcset="small.jpg 300w, medium.jpg 600w, large.jpg 900w" sizes="(max-width: 300px) 100vw, (max-width: 600px) 50vw, (max-width: 900px) 33vw, 900px" src="image.jpg" />
Обратите внимание, что у последнего размера нет медиа-условия — это значение по умолчанию. Оно будет использоваться, когда ни одно из предыдущих медиа-условий не подошло.
Будьте внимательнее к порядку объявления проверок, потому что браузер игнорирует все следующие проверки после первой успешной.
Элементы в sizes могут иметь:
-
медиа-условие
- например, (max-width: 300px) - оно описывает ширину области просмотра. (max-width: 300px) означает, что указанный размер подходит для ширины экрана от 0 до 300 CSS пикселей (включительно). Это похоже на медиа-запрос, но с некоторыми ограничениями. Вы не можете использовать screen или print. Ширина картинки
для указанного медиа-условия. Для указания ширины можно использовать разные велечины (px, em, vw), только не %. Подробнее о единицах измерения ниже.
Рассмотрим такой пример:
<img srcset="w-225.jpg 225w, w-300.jpg 300w, w-350.jpg 350w, w-640.jpg 640w" sizes="(max-width: 400px) 100vw, (max-width: 700px) 50vw, (max-width: 900px) 33vw, 225px" src="women-dress.jpg" >
- Если ширина области просмотра превышает 900px, картинка занимает фиксированную ширину 225px.
- До 900px картинка занимает 33vw, т.е. 33% от ширины окна просмотра.
- До 700px, картинка занимает 50vw, т.е. 50% от ширины окна просмотра.
- До 400px, картинка занимает 100vw, т.е. всю ширину окна просмотра.
На основе этих данных бразуер выберет одну из картинок из сета srcset (включая все проверки с DPR - см описание srcset).
Единицы измерения для sizes
Ниже показан весь список возможных единиц измерения, которые можно использовать в атрибуте sizes.
ед.измерения | значение |
---|---|
em | размер шрифта элемента |
ex | высота строчных букв шрифта элемента (высота буквы «x») |
ch | ширина "0" (ZERO, U+0030) для шрифта элемента |
rem | размер шрифта корневого элемента (html) |
vw | 1% от ширины viewport (viewport width) |
vh | 1% от высоты viewport (viewport height) |
vmin | 1% от меньшего размера viewport (меньший из vw или vh) |
vmax | 1% от большего размера viewport (больший из vw или vh) |
Поддержка браузерами sizes и srcset
WordPress функции srcset и sizes
Как отключить srcset и sizes у картинок WordPress
/** * Отключаем srcset и sizes для картинок в WordPress. * * @version 1.0 */ if( 'Disable srcset/sizes' ){ // Отменяем srcset - выходим сразу, этот фильтр лучше чем 'wp_calculate_image_srcset' add_filter( 'wp_calculate_image_srcset_meta', '__return_null' ); // Отменяем sizes - это поздний фильтр, но раннего как для srcset пока нет... add_filter( 'wp_calculate_image_sizes', '__return_false', 99 ); // Удаляем фильтр, который добавляет srcset ко всем картинкам в тексте записи // WP < 5.5 remove_filter( 'the_content', 'wp_make_content_images_responsive' ); // WP > 5.5 add_filter( 'wp_img_tag_add_srcset_and_sizes_attr', '__return_false' ); }
Дополнительный фильтр, который удаляет атрибуты srcset и sizes в последний момент. в 99% случаев этот хук не нужен, можно использовать на всякий случай
// Очищаем атрибуты `srcset` и `sizes`, если по каким-то причинам они остались. add_filter( 'wp_get_attachment_image_attributes', 'unset_attach_srcset_attr', 99 ); function unset_attach_srcset_attr( $attr ){ foreach( array('sizes','srcset') as $key ){ if( isset($attr[ $key ]) ) unset($attr[ $key ]); } return $attr; }
Подробнее читайте в этом вопросе
HTML тег <picture>
Build In Post
Для того, чтобы выводить разные изображение в зависимости от устройства (ширины экрана), также можно использовать тег <picture>
.
<picture>
— это обертка для элементов <source>
и <img>
, которая дает браузеру возможность выбрать источник.
<img>
тег тут очень важен - без него <picture> не может существовать. Это элемент для которого будут применены данные из <source> после того как будет выбран подходящий <source>.
Сам по себе тег <picture> – это более развитый аналог тега <img> и обладает интуитивно понятным синтаксисом.
<picture> выигрывает у атрибутов sizes и srcset в <img> в двух случаях:
1) Когда используются разные форматы изображений.
<picture>
позволяет использовать новые форматы (webp, avif) и не бояться за поддержку старых браузеров. Для этого можно указать MIME-тип картинки в type
атрибуте, браузер «возьмет» первый поддерживаемый тип.
Выбор/анализ подходящего варианта идет сверху вниз (будет использован первый подходходящий вариант):
<picture> <source type="image/svg+xml" srcset="my-photo.svg"> <source type="image/webp" srcset="my-photo.webp"> <source srcset="my-photo.png"> <img src="my-photo.png" alt=""> </picture>
- Тип изображение указанного в
<source>
должен соответствовать типу указанному вtype
. - Не используйте атрибут
media
, если вам не нужно художественное оформление. - Также можно использовать
srcset
иsizes
.
Нескольких размеров (под ретину):
<picture> <source type="image/avif" srcset="my-photo.avif 1x, my-photo@2x.avif 2x"> <source type="image/webp" srcset="my-photo.webp 1x, my-photo@2x.webp 2x"> <img class="some-class" src="my-photo.png" alt="Icon" srcset="my-photo.png 1x, my-photo@2x.png 2x"> </picture>
Аттрибут media
В теге source также можно использвать аттрибут media, чтобы указать ширину экрана для которой должен использоваться указанный source:
<picture> <source media="(max-width: 799px)" srcset="my-photo-portrait.jpg"> <source media="(min-width: 800px)" srcset="my-photo.jpg"> <img src="my-photo.jpg" alt="Some text"> </picture>
Аттрибут sizes
Позволяет указать размер картинки (width) для указанного размера экрана:
<picture> <source type="image/webp" srcset="my-photo-lg.webp 1200w, my-photo-md.webp 800w, my-photo-sm.webp 500w" sizes="(max-width: 800px) 90vw, (max-width: 500px) 70vw, 50vw" > <img srcset="my-photo-lg.jpg 1200w, my-photo-md.jpg 800w, my-photo-sm.jpg 500w" sizes="(max-width: 800px) 90vw, (max-width: 500px) 70vw, 50vw" src="my-photo-lg.jpg" width="280" height="460" > </picture>
2) При Художественном оформлении.
Художественное оформление — это прием, когда для разных размеров экрана показываются разные изображения. Например, у нас есть пейзаж с человеком по середине. Для большого экрана такая картинка подходит, потому что можно легко разглядеть человека, а для маленького будет лучше показать кадрированную картинку, на которой человек увеличен.
Например у нас есть картинка, которая нуждается в художественном оформлении:
<img src="my-photo.jpg" alt="">
Исправим её с помощью <picture>
.
<picture> <source media="(max-width: 800px)" srcset="my-photo-portrait.jpg"> <source media="(min-width: 800px)" srcset="my-photo.jpg"> <img src="my-photo.jpg" alt=""> </picture>

Комментарии к коду:
-
media
атрибут элемента <source> содержит медиа-условие, используя которое бразуер выбирает какую картинку нужно использовать. Из примера выше, если ширина экрана (viewport) 800 или меньше, то будет выведено изображение первого элемента <source>, если больше — второго. -
srcset
атрибут содержит URL картинки. Здесь также можно указать группу предписаний и добавить атрибутsizes
, однако используя <picture> тег это вряд ли будет продуктивно. <img src="" alt="">
с атрибутамиsrc
иalt
перед закрывающем тегом</picture>
, должен быть обязательно указан, иначе изображения не появятся! Этот тег нужен для роботов и когда браузер не может выбрать изображение по указанным условиям.
Показывать разные изображение (художественное оформление) можно и через srcset, но через <picture>
удобнее.
Поддержка бразуерами
Тег <picture> для SEO и почему о нем нужно забыть
С помощью этого тега легко и безболезненно переходить на внедрение альтернативных графических форматов. Достаточно просто перечислить внутри этого тега наши картинки (jpeg, png, webp) и браузер сам примет решение, какое из них взять.
Если вы решите серьезно заниматься технической оптимизацией, то следует забыть про тег <picture>
Потому что, когда вы начнете формировать вывод с тегом <picture> то же самое, что через тег <img> – это даст минимум троекратное увеличение узлов в DOM-дереве на каждое изображение. Верхняя граница вашего DOM-дерева оптимально должна быть в среднем 1500 узлов. У многих эта граница превышена. А каждый узел DOM-дерева – это расход памяти и замедление скриптов.
Источник: https://www.seonews.ru/analytics/kak-zanyat-top-pri-pomoshchi-odnogo-izobrazheniya/
Зачем нужен srcset и почему CSS и JavaScript не подходят?
При загрузке страницы, браузер начинает загрузку изображений до загрузки и интерпритации CSS и JavaScript. Такая техника уменьшает время загрузки страницы, в среднем, на 20%. Но она не подходит для создания адаптивных изображений, для этого и был создан srcset
атрибут.
Например, невозможно было бы загрузить элемент <img>
, затем определить ширину экрана при помощи JavaScript и динамически изменить URL картинки. Изначальное изображение было бы уже загружено (или было бы отправлено к загрузке) к моменту загрузки его меньшей версии.
Полезные ссылки
--
- Про атрибут srcset: https://serpstat.com/ru/blog/kak-ispolzovat-atribut-srcset-tega-img/
- Про лейзи лоад и srcset https://youtube.com/watch?v=v8yM0-VIM30&t=1633s
- https://imagekit.io/responsive-images/