Адаптивные изображения — Примеры
Пример 1 — Главное изображение, которое браузер не может оценить
У главного изображения три файла-кандидата, оно загружается отложенно и не объявляет ни отображаемую ширину, ни собственный размер. На телефоне браузер скачивает файл 1600px, и вёрстка прыгает, как только он приходит. Скажите, для чего был нужен каждый из пропущенных атрибутов, и исправьте разметку.
<img
src="hero-1600.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
loading="lazy"
alt="A workshop at sunset"
/>
Решение
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
sizes="(min-width: 60rem) 50vw, 100vw"
width="1600" height="900"
alt="A workshop at sunset"
/>
Без sizes браузер считает, что изображение занимает всю ширину окна, поэтому телефон шириной 400px всё равно проходит по критерию для самого крупного кандидата и скачивает файл, большая часть которого затем выбрасывается. Атрибут sizes сообщает отображаемую ширину при каждой ширине окна — именно эта информация и нужна для выбора. Атрибуты width и height резервируют область 16:9 до прихода файла, поэтому текст под изображением не сдвигается; CSS всё равно может задать отображаемый размер, ведь атрибуты дают только собственное соотношение сторон. Однако loading="lazy" на главном изображении неуместен: он задерживает самый крупный видимый элемент, а именно его и измеряет показатель загрузки; для изображений за пределами экрана этот атрибут и предназначен.
Пример 2 — Современный формат, за которым ничего нет
Элемент picture предлагает два современных формата и не даёт запасного варианта, поэтому браузер, не умеющий декодировать ни один из них, показывает сломанное изображение. Объясните, как браузер выбирает источник, и сделайте запасной вариант настоящим.
<picture>
<source srcset="hero-1600.avif" />
<source srcset="hero-1600.webp" />
</picture>
Решение
<picture>
<source type="image/avif" srcset="hero-1600.avif" media="(min-width: 60rem)" />
<source type="image/webp" srcset="hero-1600.webp" media="(min-width: 60rem)" />
<img src="hero-1600.jpg" width="1600" height="900" alt="A workshop at sunset" />
</picture>
Браузер перебирает источники по порядку и берёт первый, который понимает; поэтому современный формат идёт первым, и поэтому же важен атрибут type: без него браузер может скачать файл, который не сумеет декодировать. <img> обязателен: это запасной вариант, который отрисует любой браузер, и файл для него должен быть действительно корректным, а не заглушкой. Именно media у источника делает <picture> полезным не только для формата, но и для смены кадра — широкий кадр на больших экранах и высокий во всех остальных случаях, — а srcset внутри него по-прежнему отвечает за разрешение.