Пошук уроків, статей та іншого контенту
Оптимізуєте зображення для різних екранів через max-width, srcset, sizes і picture без виходу за межі контейнера.
Зображення, яке добре виглядає на широкому моніторі, може створювати проблеми на смартфоні:
виходити за межі контейнера;
збільшувати горизонтальну прокрутку;
завантажувати надто великий файл на повільному мобільному з’єднанні;
бути недостатньо чітким на екранах із високою щільністю пікселів;
мати невдалу композицію у вузькому форматі.
Адаптивні зображення вирішують ці проблеми на двох рівнях:
CSS керує розміром зображення на сторінці.
HTML допомагає браузеру вибрати відповідний файл для конкретного екрана.
Базове правило для адаптивних зображень:
img {
max-width: 100%;
height: auto;
}max-width: 100% не дозволяє зображенню бути ширшим за батьківський елемент.
height: auto зберігає початкові пропорції зображення.
<article class="card">
<img src="images/landscape.jpg" alt="Гірський пейзаж">
<h2>Подорож у гори</h2>
</article>.card {
max-width: 480px;
margin: 0 auto;
padding: 16px;
}
.card img {
display: block;
max-width: 100%;
height: auto;
}Якщо оригінальне зображення має ширину 1200px, а контейнер — 480px, браузер відобразить його шириною не більше ніж 480px.
display: blockЗа замовчуванням img є рядковим елементом. Через це під ним інколи залишається невеликий проміжок, пов’язаний із базовою лінією тексту.
img {
display: block;
}Це не впливає на вибір файлу, але робить поведінку зображення передбачуванішою в макеті.
srcsetmax-width змінює лише відображуваний розмір. Якщо в HTML вказано великий файл, мобільний пристрій все одно може завантажити цей файл, навіть коли показує його в маленькому розмірі.
Атрибут srcset дозволяє передати браузеру кілька варіантів зображення:
<img
src="images/forest-800.jpg"
srcset="
images/forest-400.jpg 400w,
images/forest-800.jpg 800w,
images/forest-1200.jpg 1200w
"
alt="Лісова дорога"
>Позначення 400w, 800w і 1200w — це дескриптори ширини. Вони повідомляють браузеру реальну ширину відповідного файлу в пікселях.
Атрибут src залишається резервним варіантом. Він потрібен для браузерів, які не використовують srcset, а також є обов’язковим для коректного опису зображення.
Самого srcset недостатньо, якщо зображення займає різну ширину в різних частинах макета. Для цього використовується sizes.
sizessizes повідомляє браузеру, якою приблизно буде ширина зображення на сторінці до завантаження файлу.
<img
src="images/article-800.jpg"
srcset="
images/article-400.jpg 400w,
images/article-800.jpg 800w,
images/article-1200.jpg 1200w
"
sizes="
(max-width: 600px) 100vw,
(max-width: 1000px) 70vw,
800px
"
alt="Кав'ярня на вулиці"
>Цей запис означає:
при ширині вікна до 600px зображення займає всю ширину вікна — 100vw;
при ширині до 1000px воно займає приблизно 70vw;
на більших екранах його ширина становить не більше 800px.
vw — це відсоток ширини вікна перегляду:
100vw — 100% ширини вікна;
70vw — 70% ширини вікна.
Браузер використовує значення з sizes, враховує щільність пікселів екрана та вибирає відповідний варіант із srcset.
Для такого коду:
<img
src="images/photo-800.jpg"
srcset="
images/photo-400.jpg 400w,
images/photo-800.jpg 800w,
images/photo-1600.jpg 1600w
"
sizes="(max-width: 700px) 100vw, 800px"
alt="Місто на заході сонця"
>браузер приблизно виконує такі кроки:
Визначає ширину області, у якій буде показано зображення.
Враховує щільність пікселів пристрою.
Обирає найбільш доречний файл із srcset.
Завантажує його з урахуванням доступної мережі та кешу.
Тому на смартфоні може бути завантажено файл 400w, а на великому екрані — 1600w.
У цьому прикладі зображення:
не виходить за межі контейнера;
має кілька розмірів для різних екранів;
займає всю ширину на мобільних пристроях;
обмежене шириною контенту на великих екранах.
<!doctype html>
<html lang="uk">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Адаптивне зображення</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial, sans-serif;
background: #f2f2f2;
color: #222;
}
.article {
width: min(100% - 32px, 900px);
margin: 32px auto;
padding: 24px;
background: white;
}
.article img {
display: block;
width: 100%;
max-width: 100%;
height: auto;
}
.article h1 {
margin: 24px 0 12px;
}
</style>
</head>
<body>
<main class="article">
<img
src="images/mountains-800.jpg"
srcset="
images/mountains-400.jpg 400w,
images/mountains-800.jpg 800w,
images/mountains-1200.jpg 1200w,
images/mountains-1800.jpg 1800w
"
sizes="
(max-width: 600px) calc(100vw - 32px),
(max-width: 932px) calc(100vw - 32px),
852px
"
alt="Гори, вкриті снігом"
>
<h1>Мандрівка до гір</h1>
<p>
Адаптивне зображення займає доступну ширину контейнера,
але браузер не завантажує більший файл без потреби.
</p>
</main>
</body>
</html>У прикладі ширина .article дорівнює ширині вікна мінус 32px, але не перевищує 900px. Внутрішні відступи зменшують доступну ширину зображення до 852px на великих екранах.
picturesrcset обирає різний розмір тієї самої композиції. Іноді цього недостатньо: на мобільному екрані потрібно показати не зменшену версію широкого зображення, а окрему вертикальну композицію.
Для цього використовується елемент picture:
<picture>
<source
media="(max-width: 700px)"
srcset="images/city-mobile.jpg"
>
<img
src="images/city-desktop.jpg"
alt="Міська площа ввечері"
>
</picture>Якщо ширина вікна не перевищує 700px, браузер використовує city-mobile.jpg. В інших випадках використовується зображення з img.
Важливо:
img всередині picture є обов’язковим резервним варіантом;
alt потрібно вказувати саме в img;
CSS для img усе одно застосовується.
picture,
picture img {
display: block;
width: 100%;
max-width: 100%;
}
picture img {
height: auto;
}picture із srcset і sizesУ кожному source також можна вказати кілька варіантів ширини:
<picture>
<source
media="(max-width: 600px)"
srcset="
images/portrait-400.jpg 400w,
images/portrait-800.jpg 800w
"
sizes="100vw"
>
<source
media="(min-width: 601px)"
srcset="
images/landscape-800.jpg 800w,
images/landscape-1200.jpg 1200w,
images/landscape-1600.jpg 1600w
"
sizes="80vw"
>
<img
src="images/landscape-1200.jpg"
alt="Озеро серед лісу"
>
</picture>У цьому випадку:
на вузьких екранах використовується вертикальна композиція;
на широких екранах — горизонтальна;
для кожної композиції браузер може вибрати оптимальний розмір файлу.
Умови source перевіряються зверху вниз. Браузер використовує перший відповідний source, тому порядок умов має значення.
picturepicture також можна використати, щоб запропонувати сучасний формат, а img залишити як запасний варіант:
<picture>
<source
type="image/avif"
srcset="
images/photo-800.avif 800w,
images/photo-1200.avif 1200w
"
sizes="(max-width: 700px) 100vw, 800px"
>
<source
type="image/webp"
srcset="
images/photo-800.webp 800w,
images/photo-1200.webp 1200w
"
sizes="(max-width: 700px) 100vw, 800px"
>
<img
src="images/photo-1200.jpg"
srcset="
images/photo-800.jpg 800w,
images/photo-1200.jpg 1200w
"
sizes="(max-width: 700px) 100vw, 800px"
alt="Морський пейзаж"
>
</picture>Браузер спочатку перевіряє підтримку AVIF, потім WebP, а якщо ці формати недоступні — використовує JPEG із img.
width і height у HTMLДля зображень корисно вказувати початкові width і height:
<img
src="images/office-1200.jpg"
width="1200"
height="800"
alt="Робоче місце в офісі"
>Ці атрибути описують співвідношення сторін зображення. Разом із адаптивним CSS вони не заважають зображенню зменшуватися:
img {
display: block;
max-width: 100%;
height: auto;
}Браузер може заздалегідь зарезервувати правильну висоту під зображення, тому вміст сторінки менше зміщується під час завантаження.
Використовуйте:
img {
max-width: 100%;
height: auto;
}коли:
достатньо одного файлу;
зображення невелике;
оптимізація завантаження не є важливою.
srcsetВикористовуйте srcset і sizes, коли:
композиція зображення залишається однаковою;
потрібно завантажувати різні розміри файлу;
зображення займає різну ширину в макеті.
pictureВикористовуйте picture, коли:
на різних екранах потрібні різні композиції;
потрібно запропонувати різні формати;
вибір файлу залежить від медіаумови або підтримки формату.
Помилковий варіант:
img {
width: 800px;
}Якщо контейнер на смартфоні вужчий за 800px, зображення створить горизонтальну прокрутку.
Правильніше:
img {
width: 100%;
max-width: 100%;
height: auto;
}srcset без sizesДля дескрипторів ширини 400w, 800w і 1200w браузеру потрібно знати, яку ширину зображення воно займатиме. Якщо реальна ширина відрізняється від припущення браузера, він може вибрати невдалий файл.
<img
src="images/photo-800.jpg"
srcset="
images/photo-400.jpg 400w,
images/photo-800.jpg 800w,
images/photo-1200.jpg 1200w
"
sizes="(max-width: 700px) 100vw, 800px"
alt="Опис зображення"
>sourceУсі умови source перевіряються послідовно. Загальна умова, розташована першою, може перехопити всі випадки.
<!-- Умова для вузьких екранів має бути конкретною -->
<picture>
<source media="(max-width: 600px)" srcset="images/mobile.jpg">
<source media="(min-width: 601px)" srcset="images/desktop.jpg">
<img src="images/desktop.jpg" alt="Опис зображення">
</picture>altУ picture атрибут alt вказується в резервному img:
<picture>
<source media="(max-width: 600px)" srcset="images/mobile.jpg">
<img src="images/desktop.jpg" alt="Лісова стежка">
</picture>100vw без урахування відступівЯкщо зображення знаходиться в контейнері з відступами, 100vw може бути ширшим за реальну область зображення.
Наприклад, для контейнера з горизонтальними відступами 16px доречніше:
sizes="calc(100vw - 32px)"Значення sizes має описувати фактичну ширину зображення, а не просто ширину вікна.
max-width: 100% не дозволяє зображенню вийти за межі контейнера.
height: auto зберігає пропорції.
srcset містить кілька варіантів одного зображення.
Дескриптори 400w, 800w і подібні описують реальну ширину файлів.
sizes повідомляє браузеру, яку ширину зображення потрібно врахувати в макеті.
picture дає змогу змінювати композицію або формат зображення.
Елемент img усередині picture є резервним варіантом і містить alt.
Атрибути width і height допомагають браузеру заздалегідь зарезервувати місце під зображення.