← HTML & CSS/Адаптивные изображения#46 из 383← ПредыдущийСледующий →+20 XP
Полезно по теме:Гайд: старт в frontendПрактика: DOM и событияТермин: DOMМаршрут: старт с нуля

Адаптивные изображения

Изображения — самый тяжёлый ресурс на большинстве сайтов. Средняя страница загружает 1–3 МБ картинок. Если отдавать пользователю на телефоне ту же картинку, что и на десктопе с Retina-экраном — он ждёт лишние секунды и тратит мобильный трафик. Адаптивные изображения решают эту проблему: браузер сам выбирает нужный файл в зависимости от размера экрана, плотности пикселей и поддерживаемых форматов.

Проблема: один <img> для всех

<!-- Плохо: десктопная картинка 2000×1200 грузится на мобильном -->
<img src="hero-2000.jpg" alt="Баннер">

На iPhone SE (320px) эта картинка будет сжата CSS до ширины экрана, но загрузится целиком — все 2 МБ. Нужен механизм, который позволит браузеру выбрать подходящий размер.

srcset — набор вариантов изображения

Атрибут srcset даёт браузеру список файлов с указанием их реальной ширины (дескриптор w) или плотности пикселей (дескриптор x).

Дескриптор ширины (w)

<img
  src="photo-800.jpg"
  srcset="
    photo-400.jpg   400w,
    photo-800.jpg   800w,
    photo-1200.jpg 1200w,
    photo-1600.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
  alt="Пейзаж"
>

Как это работает:

1. srcset — «у меня есть версии 400px, 800px, 1200px и 1600px шириной»

2. sizes — «на экранах до 600px картинка занимает 100% ширины, до 1024px — 50%, иначе — 33%»

3. Браузер вычисляет: «экран 375px, плотность 2x → нужна картинка 375 × 2 = 750px → выберу photo-800.jpg»

Атрибут src — фолбэк для старых браузеров, которые не понимают srcset.

Дескриптор плотности (x)

<img
  src="logo.png"
  srcset="
    logo.png    1x,
    logo@2x.png 2x,
    logo@3x.png 3x
  "
  alt="Логотип"
>

Используется для изображений фиксированного размера (логотипы, иконки), где нужно только учесть плотность пикселей.

sizes — подсказка для браузера

Без sizes браузер считает, что картинка занимает 100vw (всю ширину экрана). Это почти всегда неверно.

<!-- sizes сообщает реальный размер отображения -->
<img
  srcset="card-300.jpg 300w, card-600.jpg 600w, card-900.jpg 900w"
  sizes="(max-width: 640px) 100vw,
         (max-width: 1024px) 50vw,
         320px"
  src="card-600.jpg"
  alt="Карточка товара"
>

Правила sizes читаются слева направо, первое совпавшее условие побеждает. Последнее значение — значение по умолчанию (без условия).

<picture> — полный контроль

Элемент <picture> позволяет задавать разные изображения для разных условий: формат, размер экрана, ориентация.

Art direction — разные кадрировки

<picture>
  <!-- На мобильном — крупный портрет -->
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.jpg"
  >
  <!-- На планшете — средний кадр -->
  <source
    media="(max-width: 1023px)"
    srcset="hero-tablet.jpg"
  >
  <!-- На десктопе — широкий панорамный кадр -->
  <img src="hero-desktop.jpg" alt="Главный баннер">
</picture>

Art direction — это когда для мобильного не просто уменьшают картинку, а показывают другой кадр: крупнее лицо, другую композицию.

Выбор формата

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Фото">
</picture>

Браузер выберет первый поддерживаемый формат. AVIF легче WebP на 20–50%, WebP легче JPEG на 25–35%. Порядок важен: от самого современного к самому совместимому.

Комбинация формата и srcset

<picture>
  <source
    srcset="photo-400.avif 400w, photo-800.avif 800w, photo-1200.avif 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    type="image/avif"
  >
  <source
    srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    type="image/webp"
  >
  <img
    srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    src="photo-800.jpg"
    alt="Фото"
  >
</picture>

Ленивая загрузка (lazy loading)

<!-- Браузер загрузит картинку только когда она приблизится к видимой области -->
<img src="photo.jpg" alt="Фото" loading="lazy">

<!-- Первый экран — загружать сразу (по умолчанию) -->
<img src="hero.jpg" alt="Баннер" loading="eager">

Атрибут loading="lazy" поддерживают все современные браузеры. Не ставь его на картинки первого экрана — это замедлит LCP (Largest Contentful Paint).

fetchpriority — приоритет загрузки

<!-- Главная картинка — загрузить первой -->
<img src="hero.jpg" alt="Баннер" fetchpriority="high">

<!-- Декоративная — не торопиться -->
<img src="decoration.jpg" alt="" loading="lazy" fetchpriority="low">

CSS для адаптивных изображений

/* Базовое правило: картинка не вылезает за контейнер */
img {
  max-width: 100%;
  height: auto;
}

/* object-fit для контейнеров фиксированного размера */
.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;      /* Обрезает, сохраняя пропорции */
  object-position: center; /* Точка фокуса */
}

/* aspect-ratio — современный способ задать пропорции */
.thumbnail {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

Предотвращение сдвига макета (CLS)

Когда картинка загружается, она «раздвигает» контент. Это плохой UX и вредит SEO.

<!-- Всегда указывай width и height — браузер зарезервирует место -->
<img
  src="photo.jpg"
  width="800"
  height="600"
  alt="Фото"
  style="max-width: 100%; height: auto;"
>

Браузер использует width и height для расчёта aspect ratio до загрузки картинки.

Чек-лист адаптивных изображений

1. `max-width: 100%; height: auto;` — базовое CSS-правило для всех img

2. `width` и `height` в HTML — предотвращает сдвиг макета

3. `srcset` + `sizes` — для контентных изображений разных размеров

4. `<picture>` — для art direction или выбора формата (AVIF/WebP/JPEG)

5. `loading="lazy"` — для всего ниже первого экрана

6. `fetchpriority="high"` — для LCP-изображения (главный баннер)

7. Современные форматы — AVIF → WebP → JPEG как фолбэк

Примеры

Адаптивное изображение с srcset, sizes и выбором формата через <picture>

<!-- Пример 1: srcset с дескриптором ширины -->
<img
  src="landscape-800.jpg"
  srcset="
    landscape-400.jpg   400w,
    landscape-800.jpg   800w,
    landscape-1200.jpg 1200w
  "
  sizes="(max-width: 600px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
  alt="Горный пейзаж"
  loading="lazy"
  width="1200"
  height="800"
  style="max-width: 100%; height: auto;"
>

<!-- Пример 2: <picture> с art direction и форматами -->
<picture>
  <!-- Мобильный: вертикальный кадр в AVIF -->
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.avif"
    type="image/avif"
  >
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.webp"
    type="image/webp"
  >
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.jpg"
  >

  <!-- Десктоп: панорамный кадр -->
  <source srcset="hero-desktop.avif" type="image/avif">
  <source srcset="hero-desktop.webp" type="image/webp">

  <img
    src="hero-desktop.jpg"
    alt="Главный баннер сайта"
    fetchpriority="high"
    width="1920"
    height="600"
    style="max-width: 100%; height: auto;"
  >
</picture>

<!-- Пример 3: CSS object-fit для карточки -->
<style>
  .product-card img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 8px;
  }
</style>

<div class="product-card">
  <img
    src="product.jpg"
    srcset="product-300.jpg 300w, product-600.jpg 600w"
    sizes="(max-width: 640px) 100vw, 300px"
    alt="Товар"
    loading="lazy"
  >
</div>

Адаптивные изображения

Изображения — самый тяжёлый ресурс на большинстве сайтов. Средняя страница загружает 1–3 МБ картинок. Если отдавать пользователю на телефоне ту же картинку, что и на десктопе с Retina-экраном — он ждёт лишние секунды и тратит мобильный трафик. Адаптивные изображения решают эту проблему: браузер сам выбирает нужный файл в зависимости от размера экрана, плотности пикселей и поддерживаемых форматов.

Проблема: один <img> для всех

<!-- Плохо: десктопная картинка 2000×1200 грузится на мобильном -->
<img src="hero-2000.jpg" alt="Баннер">

На iPhone SE (320px) эта картинка будет сжата CSS до ширины экрана, но загрузится целиком — все 2 МБ. Нужен механизм, который позволит браузеру выбрать подходящий размер.

srcset — набор вариантов изображения

Атрибут srcset даёт браузеру список файлов с указанием их реальной ширины (дескриптор w) или плотности пикселей (дескриптор x).

Дескриптор ширины (w)

<img
  src="photo-800.jpg"
  srcset="
    photo-400.jpg   400w,
    photo-800.jpg   800w,
    photo-1200.jpg 1200w,
    photo-1600.jpg 1600w
  "
  sizes="(max-width: 600px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
  alt="Пейзаж"
>

Как это работает:

1. srcset — «у меня есть версии 400px, 800px, 1200px и 1600px шириной»

2. sizes — «на экранах до 600px картинка занимает 100% ширины, до 1024px — 50%, иначе — 33%»

3. Браузер вычисляет: «экран 375px, плотность 2x → нужна картинка 375 × 2 = 750px → выберу photo-800.jpg»

Атрибут src — фолбэк для старых браузеров, которые не понимают srcset.

Дескриптор плотности (x)

<img
  src="logo.png"
  srcset="
    logo.png    1x,
    logo@2x.png 2x,
    logo@3x.png 3x
  "
  alt="Логотип"
>

Используется для изображений фиксированного размера (логотипы, иконки), где нужно только учесть плотность пикселей.

sizes — подсказка для браузера

Без sizes браузер считает, что картинка занимает 100vw (всю ширину экрана). Это почти всегда неверно.

<!-- sizes сообщает реальный размер отображения -->
<img
  srcset="card-300.jpg 300w, card-600.jpg 600w, card-900.jpg 900w"
  sizes="(max-width: 640px) 100vw,
         (max-width: 1024px) 50vw,
         320px"
  src="card-600.jpg"
  alt="Карточка товара"
>

Правила sizes читаются слева направо, первое совпавшее условие побеждает. Последнее значение — значение по умолчанию (без условия).

<picture> — полный контроль

Элемент <picture> позволяет задавать разные изображения для разных условий: формат, размер экрана, ориентация.

Art direction — разные кадрировки

<picture>
  <!-- На мобильном — крупный портрет -->
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.jpg"
  >
  <!-- На планшете — средний кадр -->
  <source
    media="(max-width: 1023px)"
    srcset="hero-tablet.jpg"
  >
  <!-- На десктопе — широкий панорамный кадр -->
  <img src="hero-desktop.jpg" alt="Главный баннер">
</picture>

Art direction — это когда для мобильного не просто уменьшают картинку, а показывают другой кадр: крупнее лицо, другую композицию.

Выбор формата

<picture>
  <source srcset="photo.avif" type="image/avif">
  <source srcset="photo.webp" type="image/webp">
  <img src="photo.jpg" alt="Фото">
</picture>

Браузер выберет первый поддерживаемый формат. AVIF легче WebP на 20–50%, WebP легче JPEG на 25–35%. Порядок важен: от самого современного к самому совместимому.

Комбинация формата и srcset

<picture>
  <source
    srcset="photo-400.avif 400w, photo-800.avif 800w, photo-1200.avif 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    type="image/avif"
  >
  <source
    srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    type="image/webp"
  >
  <img
    srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
    sizes="(max-width: 768px) 100vw, 50vw"
    src="photo-800.jpg"
    alt="Фото"
  >
</picture>

Ленивая загрузка (lazy loading)

<!-- Браузер загрузит картинку только когда она приблизится к видимой области -->
<img src="photo.jpg" alt="Фото" loading="lazy">

<!-- Первый экран — загружать сразу (по умолчанию) -->
<img src="hero.jpg" alt="Баннер" loading="eager">

Атрибут loading="lazy" поддерживают все современные браузеры. Не ставь его на картинки первого экрана — это замедлит LCP (Largest Contentful Paint).

fetchpriority — приоритет загрузки

<!-- Главная картинка — загрузить первой -->
<img src="hero.jpg" alt="Баннер" fetchpriority="high">

<!-- Декоративная — не торопиться -->
<img src="decoration.jpg" alt="" loading="lazy" fetchpriority="low">

CSS для адаптивных изображений

/* Базовое правило: картинка не вылезает за контейнер */
img {
  max-width: 100%;
  height: auto;
}

/* object-fit для контейнеров фиксированного размера */
.card-image {
  width: 100%;
  height: 200px;
  object-fit: cover;      /* Обрезает, сохраняя пропорции */
  object-position: center; /* Точка фокуса */
}

/* aspect-ratio — современный способ задать пропорции */
.thumbnail {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

Предотвращение сдвига макета (CLS)

Когда картинка загружается, она «раздвигает» контент. Это плохой UX и вредит SEO.

<!-- Всегда указывай width и height — браузер зарезервирует место -->
<img
  src="photo.jpg"
  width="800"
  height="600"
  alt="Фото"
  style="max-width: 100%; height: auto;"
>

Браузер использует width и height для расчёта aspect ratio до загрузки картинки.

Чек-лист адаптивных изображений

1. `max-width: 100%; height: auto;` — базовое CSS-правило для всех img

2. `width` и `height` в HTML — предотвращает сдвиг макета

3. `srcset` + `sizes` — для контентных изображений разных размеров

4. `<picture>` — для art direction или выбора формата (AVIF/WebP/JPEG)

5. `loading="lazy"` — для всего ниже первого экрана

6. `fetchpriority="high"` — для LCP-изображения (главный баннер)

7. Современные форматы — AVIF → WebP → JPEG как фолбэк

Примеры

Адаптивное изображение с srcset, sizes и выбором формата через <picture>

<!-- Пример 1: srcset с дескриптором ширины -->
<img
  src="landscape-800.jpg"
  srcset="
    landscape-400.jpg   400w,
    landscape-800.jpg   800w,
    landscape-1200.jpg 1200w
  "
  sizes="(max-width: 600px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
  alt="Горный пейзаж"
  loading="lazy"
  width="1200"
  height="800"
  style="max-width: 100%; height: auto;"
>

<!-- Пример 2: <picture> с art direction и форматами -->
<picture>
  <!-- Мобильный: вертикальный кадр в AVIF -->
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.avif"
    type="image/avif"
  >
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.webp"
    type="image/webp"
  >
  <source
    media="(max-width: 767px)"
    srcset="hero-mobile.jpg"
  >

  <!-- Десктоп: панорамный кадр -->
  <source srcset="hero-desktop.avif" type="image/avif">
  <source srcset="hero-desktop.webp" type="image/webp">

  <img
    src="hero-desktop.jpg"
    alt="Главный баннер сайта"
    fetchpriority="high"
    width="1920"
    height="600"
    style="max-width: 100%; height: auto;"
  >
</picture>

<!-- Пример 3: CSS object-fit для карточки -->
<style>
  .product-card img {
    width: 100%;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    border-radius: 8px;
  }
</style>

<div class="product-card">
  <img
    src="product.jpg"
    srcset="product-300.jpg 300w, product-600.jpg 600w"
    sizes="(max-width: 640px) 100vw, 300px"
    alt="Товар"
    loading="lazy"
  >
</div>

Задание

Создай адаптивное изображение товара с использованием `<picture>` и `srcset`. На мобильных устройствах (до 767px) покажи вертикальное фото товара (`product-mobile.jpg`), на десктопе — горизонтальное (`product-desktop.jpg`). Добавь поддержку WebP-формата для обоих вариантов. Изображение должно использовать ленивую загрузку и не вызывать сдвигов макета.

Подсказка

Используй элемент `<picture>` для обёртки. Мобильные `<source>` имеют `media="(max-width: 767px)"`. Для WebP укажи `type="image/webp"` и расширение `.webp`. Фолбэк `<img>` с `src="product-desktop.jpg"`. `loading="lazy"` для ленивой загрузки. `height: auto` в CSS чтобы сохранить пропорции.

Загружаем среду выполнения...
Загружаем AI-помощника...