Атрибут sizes (от английского sizes, «размеры») сообщает браузеру, какую ширину картинка займёт на странице. Закрывающей части у него нет, он записывается внутри открывающего тега: sizes="50vw". Закрывающий тег нужен самому элементу не всегда: у <img> и <source> его нет. Работает атрибут только вместе с srcset, в котором файлы описаны дескриптором w.
Зачем эта подсказка нужна. Браузер выбирает файл раньше, чем успеет построить страницу и узнать настоящую ширину картинки, поэтому ему нужна заранее записанная оценка. Если оценка точная, он скачает наименьший подходящий файл. Если нет, получится либо размытая картинка, либо лишние килобайты.
<img src="cat-640.jpg"
srcset="cat-640.jpg 640w, cat-1280.jpg 1280w"
sizes="(min-width: 800px) 50vw, 100vw"
alt="Кот на подоконнике">
В этой статье
- Что такое атрибут sizes в HTML и зачем он нужен
- Для каких тегов работает sizes: img и source
- Как записать sizes: условия, ширина слота и запятые
- Какие значения и единицы допустимы: vw, px, em и calc()
- Условия media в sizes: ширина окна, ориентация и плотность
- Как подобрать sizes под реальную ширину картинки
- Sizes="auto" и loading="lazy": ширина из вёрстки
- Sizes у source и у img внутри picture
- Частые ошибки в атрибуте sizes
- Шпаргалка по атрибуту sizes
Что такое атрибут sizes в HTML и зачем он нужен
Список файлов в srcset с дескрипторами w говорит только о том, какой ширины каждый файл. Чтобы выбрать из них один, браузер должен знать вторую величину: сколько пикселей картинка займёт на странице. Её он умножает на плотность пикселей экрана и берёт наименьший файл, которого хватает. Эту вторую величину и записывают в sizes.
Важно, чем sizes не является. Он не задаёт размер картинки: размер по-прежнему задают стили и атрибуты width и height. sizes только описывает этот размер браузеру заранее, поэтому его значение нужно согласовывать с вёрсткой самому. Если файлы описаны дескрипторами x, атрибут не нужен вовсе.
- Без
srcsetс дескрипторамиwатрибутsizesничего не делает: остаётся адрес изsrc. - Без самого
sizesбраузер считает, что картинка занимает всю ширину окна, как при100vw. - Прочитать записанное значение из скрипта можно через свойство
img.sizes.
Для каких тегов работает sizes: img и source
Атрибут есть у двух тегов. Смысл у него один, но роль в разметке разная.
| Тег | Что делает sizes | Пример записи |
|---|---|---|
<img> | Описывает ширину самой картинки на странице | <img srcset="a.jpg 640w, b.jpg 1280w" sizes="100vw" alt="Кот"> |
<source> внутри <picture> | Описывает ширину картинки для одного условия: окна определённой ширины или формата | <source srcset="a.webp 640w, b.webp 1280w" sizes="50vw"> |
Для предварительной загрузки картинки через link есть отдельный атрибут imagesizes, он разобран в этой же группе справочника чуть позже.
Как записать sizes: условия, ширина слота и запятые
Значение sizes это список через запятую. Каждый элемент включает необязательное условие в скобках и ширину, которую назовём слотом. Последний элемент обычно пишут без условия: он работает как запасной.
| Часть | Что это | Пример записи |
|---|---|---|
| Условие | Условие media в скобках, как в CSS | (min-width: 800px) |
| Слот | Ширина картинки: число с единицей, vw или calc() | 50vw |
| Элемент списка | Условие и слот через пробел | (min-width: 800px) 50vw |
| Запасной элемент | Слот без условия, записывается последним | 100vw |
| Разделитель | Запятая между элементами | (min-width: 800px) 50vw, 100vw |
Браузер читает список слева направо и берёт первый элемент, условие которого выполнено. Остальные он уже не смотрит. Если не подошло ни одно условие и запасного нет, берётся 100vw. В браузере, на котором я проверял, список (min-width: 600px) 300px на окне шириной 400 дал слот 400.
sizes="(min-width: 1200px) 600px,
(min-width: 800px) 50vw,
100vw"
Какие значения и единицы допустимы: vw, px, em и calc()
Слот записывают числом с единицей длины, как в CSS. Ниже результаты для файлов шириной 320, 640, 960 и 1280 пикселей на окне 800 при плотности 1.
| Запись | Слот в пикселях | Выбранный файл |
|---|---|---|
50vw | 400 | 640 |
400px | 400 | 640 |
20em | 320 (em равен 16 пикселям) | 320 |
20rem | 320 | 320 |
100vh | 600 (высота окна) | 640 |
calc(100vw - 100px) | 700 | 960 |
calc(50vw + 20px) | 420 | 640 |
0 | 0 | 320, наименьший из списка |
Часть записей браузер отбрасывает и считает, что sizes записан неправильно. Тогда он берёт слот 100vw, то есть всю ширину окна, и выбирает самый большой файл.
| Запись | Что показал браузер | Пример записи |
|---|---|---|
| Проценты | Отброшено: слот 100vw, файл 960 | sizes="50%" |
| Отрицательная ширина | Отброшено | sizes="-100px" |
| Число без единицы | Отброшено, кроме нуля | sizes="300" |
Проценты в calc() | Отброшено | sizes="calc(100% - 40px)" |
| Пустое значение | Отброшено, валидатор показывает ошибку | sizes="" |
| Произвольный текст | Отброшено | sizes="garbage" |
Проценты стандарт не допускает: вместо них берут vw и calc(). Проверку записи делает валидатор: сообщение о пустом значении разобрано на странице Rocket Validator. Регистр единиц не важен: 100VW работает.
Пример: как браузер читает значение sizes
Выберите значение или впишите своё. Окно демонстрации узкое, поэтому слоты небольшие. Строка «Нужно пикселей» показывает слот, умноженный на плотность вашего экрана.
Файл выбирает ваш браузер, результат может отличаться от моих замеров. Единица vw считается от ширины окна самой демонстрации.
Условия media в sizes: ширина окна, ориентация и плотность
Условия в sizes записывают так же, как в CSS. Чаще всего это ширина окна: на широком экране картинка занимает меньшую долю, на узком всю ширину. Поддерживаются и другие условия, например ориентация и плотность пикселей.
| Окно и плотность | Запись sizes | Слот | Выбранный файл |
|---|---|---|---|
| 800, 1 | (min-width: 600px) 300px, 100vw | 300 | 320 |
| 800, 1 | (max-width: 500px) 100vw, 300px | 300 (первое условие не выполнено) | 320 |
| 800, 1 | (min-width: 600px) 300px, (min-width: 300px) 500px, 100vw | 300 (первое подходящее) | 320 |
| 800, 1 | (min-width: 300px) 500px, (min-width: 600px) 300px | 500 (порядок изменил результат) | 640 |
| 800, 1 | 100vw, 200px | 800 (запасной элемент записан первым) | 960 |
| 800, 1 | (orientation: landscape) 200px, 100vw | 200 | 320 |
| 800, 1 | (min-resolution: 2dppx) 200px, 100vw | 800 (условие не выполнено) | 960 |
| 800, 2 | (min-width: 600px) 300px, 100vw | 300, нужно 600 пикселей | 640 |
Две строки таблицы нужно запомнить. Порядок важен: условие с меньшим порогом, записанное раньше, перекрывает более строгое после него. А элемент без условия работает только последним: если поставить его первым, остальные не сработают никогда.
sizes="(min-width: 1200px) 600px,
(min-width: 800px) 50vw,
100vw"
Пример: какое условие в sizes сработает
В демонстрации слоты записаны в пикселях, а файлы имеют ширину 150, 300, 600 и 1200. Строка «Сработал вариант» показывает, какой элемент списка сработал в вашем окне.
Условия проверяет ваш браузер на окне самой демонстрации, поэтому у посетителей результаты будут разными.
Как подобрать sizes под реальную ширину картинки
Значение sizes должно повторять вёрстку: сколько пикселей картинка занимает в каждом состоянии окна. Если записать неверное число, браузер доверится ему, а не реальной ширине, и выберет не тот файл. Типовые случаи собраны в таблице.
| Как картинка расположена | Запись sizes | Пример записи |
|---|---|---|
| На всю ширину окна | Всё окно | sizes="100vw" |
| В две колонки поровну | Половина окна | sizes="50vw" |
| Колонка с отступами 20 пикселей по бокам | Окно без отступов | sizes="calc(100vw - 40px)" |
| Контейнер шириной 800 по центру, на узком окне отступы 20 пикселей | Две ступени | sizes="(min-width: 840px) 800px, calc(100vw - 40px)" |
| Миниатюра фиксированной ширины | Пиксели | sizes="120px" |
Практический путь такой: сначала сверстать картинку, затем записать sizes по получившейся ширине в нескольких состояниях окна. Для контроля прочитайте img.currentSrc и сравните выбранный файл с ожидаемым. Если файл оказывается слишком большим, проверьте, не пропущено ли условие для нужной ширины окна. Подробный разбор расчёта есть в серии статей Cloud Four о responsive images.
<style>
.page { max-width: 800px; margin: 0 auto; padding: 0 20px; }
img { max-width: 100%; height: auto; }
</style>
<img srcset="a-640.jpg 640w, a-1280.jpg 1280w"
sizes="(min-width: 840px) 800px, calc(100vw - 40px)"
width="800" height="600" alt="Кот">
Sizes="auto" и loading="lazy": ширина из вёрстки
Для картинок с отложенной загрузкой атрибута loading="lazy" есть особое значение sizes="auto". Браузер подставляет реальную ширину картинки из вёрстки, и вручную считать слот не нужно. Работает оно только у ленивых картинок: файл у них загружается позже, когда ширина уже известна.
| Запись | Что получилось | Пример записи |
|---|---|---|
auto с loading="lazy", ширина 300 из атрибута | Слот 300, файл 320 | <img loading="lazy" sizes="auto" width="300" ...> |
auto с loading="lazy", ширина 150 из CSS | Слот 150, файл 320 | style="width:150px" |
auto, 100vw с loading="lazy", ширина 500 из CSS | Слот 500, файл 640 | sizes="auto, 100vw" |
auto без loading="lazy" | Значение отброшено, слот 100vw, файл 960 | sizes="auto" |
Это новая возможность, и не все программы её знают. Если значение не поддерживается, браузер поступит как с неверной записью и возьмёт 100vw. Поэтому на важных страницах auto лучше проверять в своём браузере, как в демонстрации ниже. Подробнее о самом атрибуте loading расскажет отдельная страница справочника.
<img src="cat-640.jpg"
srcset="cat-640.jpg 640w, cat-1280.jpg 1280w"
sizes="auto"
loading="lazy"
width="300" height="200" alt="Кот">
Пример: sizes="auto" у ленивой и обычной картинки
В демонстрации четыре файла шириной 100, 200, 400 и 800 пикселей. Сравните, как выбор зависит от ширины картинки и от атрибута loading.
Если ваш браузер значение auto не поддерживает, во всех вариантах выбор будет как при 100vw.
Sizes у source и у img внутри picture
Внутри <picture> у каждого <source> может быть свой sizes. Он действует только на тот srcset, рядом с которым записан. Атрибут sizes у самого img работает, лишь когда браузер выбрал его, то есть ни один source не подошёл.
<picture>
<source media="(min-width: 700px)"
srcset="wide-320.jpg 320w, wide-960.jpg 960w"
sizes="300px">
<img src="cat-640.jpg" alt="Кот">
</picture>
В браузере, на котором я проверял, при окне 800 сработал source и слот 300 дал файл шириной 320. Когда я записал sizes только у img, а source подошёл, значение было проигнорировано и слот стал равен 100vw.
Частые ошибки в атрибуте sizes
Большинство ошибок связано с тем, что sizes принимают за размер картинки, а не за подсказку, или записывают значения, которые браузер молча отбрасывает.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
sizes без srcset | Ничего не меняется, остаётся адрес из src | Добавить srcset с дескрипторами w |
sizes с дескрипторами x | Атрибут игнорируется, валидатор показывает ошибку | Перейти на дескрипторы w или убрать sizes |
sizes="50%" | Проценты отбрасываются, слот становится 100vw | Писать 50vw |
sizes="300" | Число без единицы отбрасывается | Дописать единицу: 300px |
sizes="" | Пустое значение отбрасывается, валидатор показывает ошибку | Записать слот или убрать атрибут |
calc(100% - 40px) | Проценты в calc() отбрасываются | Использовать calc(100vw - 40px) |
sizes="100vw, (min-width: 800px) 50vw" | Первый элемент без условия перекрывает остальные | Запасной слот записывать последним |
(min-width: 300px) 500px, (min-width: 600px) 300px | Порог 300 срабатывает раньше, до порога 600 дело не доходит | Сначала записывать самое строгое условие |
| Условие без запасного слота | Если условие не выполнено, берётся 100vw | Дописать запасной слот в конце |
sizes="100vw" для узкой колонки | Браузер выбирает лишний большой файл | Записать реальную ширину колонки |
sizes="auto" без loading="lazy" | Значение отбрасывается, слот 100vw | Добавить loading="lazy" или записать слот |
sizes у img внутри picture, когда подошёл source | Значение игнорируется | Записать sizes у нужного source |
Шпаргалка по атрибуту sizes
Всё главное из статьи в одной таблице.
| Задача | Как записать | Пример записи |
|---|---|---|
| Картинка на всю ширину окна | Слот 100vw | sizes="100vw" |
| Картинка в половину окна | Слот 50vw | sizes="50vw" |
| Колонка с отступами | calc() с vw | sizes="calc(100vw - 40px)" |
| Другой слот на широком окне | Условие и запасной слот | sizes="(min-width: 800px) 50vw, 100vw" |
| Фиксированная ширина | Пиксели | sizes="300px" |
| Ширина из вёрстки | auto и loading="lazy" | <img sizes="auto" loading="lazy" ...> |
| Другой слот для source | sizes у source | <source srcset="..." sizes="300px"> |
| Нельзя в sizes | Проценты, числа без единицы, пустое значение | sizes="50%" |
| Проверить результат | Свойство currentSrc | img.currentSrc |