Практическое руководство по элементу <img>: от основ до LCP
<img> кажется простым, но его неправильное использование — одна из частых причин проблем с производительностью: смещение макета, загрузка тяжёлых изображений на мобильные устройства, медленный LCP. Руководство объясняет, как и почему браузер работает с изображениями: от указания размеров и адаптивности через srcset с sizes до современных форматов в <picture>, управления приоритетами загрузки и стратегий для LCP с предварительной загрузкой.Введение
Элемент <img> — один из старейших и, на первый взгляд, самых простых элементов HTML. Достаточно указать путь к файлу в атрибуте src, и изображение появится на странице. Но за этой простотой скрывается гораздо больше возможностей, чем кажется.
При аудите веб-проектов часто встречаются одни и те же недочёты: изображения без указанных размеров, из-за которых страница «прыгает» в процессе загрузки; тяжёлые картинки, которые одинаково загружаются и на десктопе, и на мобильном устройстве; отсутствие современных форматов; неправильная настройка приоритетов для ключевых изображений. Каждая такая ошибка сама по себе кажется незначительной, но в сумме они превращаются в потерянные баллы Core Web Vitals и, что важнее, в раздражение пользователей.
Цель этой статьи — не просто перечислить атрибуты элемента <img>, а объяснить, как и почему они работают. Понимание внутренних механизмов позволяет принимать осознанные решения, а не копировать примеры из интернета в надежде, что «сработает».
Мы пройдём путь от базовых понятий — например, почему так важно указывать ширину и высоту изображения, — до продвинутых техник оптимизации, включая адаптивные изображения с srcset и sizes, современные форматы через <picture>, управление приоритетом загрузки и стратегии для улучшения Largest Contentful Paint. В финале обсудим, когда имеет смысл делегировать эти задачи Image CDN, а когда лучше оставить ручное управление.
Материал рассчитан на разработчиков, которые знакомы с основами HTML и хотят поднять качество работы с изображениями на новый уровень — чтобы сайт не просто работал, а работал быстро, предсказуемо и комфортно для пользователя на любом устройстве.
Как браузер видит изображение: понятие внутреннего размера
Прежде чем погружаться в атрибуты, управляющие адаптивностью и загрузкой, нужно понять одну фундаментальную вещь: браузер не знает размеры изображения, пока не загрузит его.
Каждый файл изображения имеет так называемый внутренний размер (intrinsic size) — естественную ширину и высоту в пикселях, заложенные в самом файле. Например, фотография, сделанная на камеру смартфона, может иметь внутренний размер 4032×3024 пикселя. Иконка, подготовленная дизайнером, — 24×24 пикселя. Эти значения хранятся в метаданных файла, и браузер может узнать их только после того, как файл будет загружен и хотя бы частично обработан.
В чём здесь проблема для производительности? Когда браузер строит страницу, он анализирует HTML и создаёт DOM-дерево. Если он встречает тег <img>, в котором не указаны width и height, он не может определить, сколько места зарезервировать под это изображение. В результате браузер отображает страницу, оставляя под изображение временное пустое место (или вовсе не оставляя его), а когда изображение наконец загружается и становятся известны его размеры, содержимое страницы сдвигается, чтобы освободить нужное пространство.
Это явление называется смещением макета (layout shift). Если оно происходит после того, как пользователь уже начал взаимодействовать со страницей (например, читать текст или пытаться нажать на кнопку), это вызывает раздражение и ухудшает пользовательский опыт. Кроме того, смещение макета измеряется метрикой CLS (Cumulative Layout Shift) — одной из трёх ключевых метрик Core Web Vitals, влияющих на ранжирование в поисковых системах.
Решение этой проблемы на удивление простое: всегда указывайте атрибуты width и height в теге <img>. Даже если планируете масштабировать изображение через CSS (например, задав width: 100%), указание исходных размеров в HTML позволяет браузеру рассчитать пропорцию (aspect ratio) и зарезервировать правильное место заранее.
<!-- Без указания размеров: браузер узнает их только после загрузки,
что приведёт к смещению макета -->
<img src="photo.jpg" alt="Горный пейзаж">
<!-- С указанием размеров: место зарезервировано сразу,
смещения макета не происходит -->
<img src="photo.jpg" width="1920" height="1080" alt="Горный пейзаж">
Важно понимать, что значения width и height в HTML задают именно внутренний размер изображения, но не ограничивают его отображение. Вы по-прежнему можете использовать CSS, чтобы изменить визуальные размеры:
img {
width: 100%;
height: auto; /* сохраняет пропорции */
}
Браузер возьмёт указанные в HTML 1920×1080, рассчитает соотношение сторон (16:9) и зарезервирует место соответствующим образом. Когда CSS скажет «занимай 100% ширины родителя», браузер уже будет знать, какую высоту оставить, чтобы пропорция не нарушилась.
Этот принцип работает для любых замещаемых элементов (replaced elements) — не только изображений, но и видео, iframe, элементов <canvas>. Во всех случаях указание размеров в HTML помогает браузеру зарезервировать пространство заранее и избежать неприятных скачков контента.
Если вы хотите глубже разобраться в природе HTML-атрибутов и их связи с DOM-свойствами, рекомендую обратиться к статье «Атрибуты и свойства HTML: в чём разница» — там этот вопрос раскрыт подробно.
Адаптивные изображения: как браузер выбирает подходящий файл
Представьте сайт, на котором в шапке используется красивое панорамное фото шириной 1920 пикселей. На широком мониторе оно смотрится отлично. Но когда тот же сайт открывается на смартфоне с экраном шириной 375 пикселей, происходит сразу две проблемы. Первая: браузер всё равно загружает файл размером 1920 пикселей, который весит, скажем, 500 килобайт, хотя для отображения на маленьком экране достаточно версии в 400 пикселей весом 50 килобайт. Это напрасная трата трафика и замедление загрузки. Вторая: если изображение содержит важные детали (например, лица людей), при таком сильном сжатии они становятся едва различимыми.
Это и есть две стороны одной проблемы, которая называется переключение разрешений (resolution switching) — необходимость предоставлять браузеру разные версии одного и того же изображения в зависимости от характеристик устройства.
Решением служат два атрибута элемента <img>: srcset и sizes. Они позволяют предложить браузеру несколько вариантов изображения с разной шириной, а браузер сам выбирает подходящий, основываясь на размере экрана, плотности пикселей и других факторах.
Как работает выбор браузера
Атрибут srcset содержит список URL-адресов с указанием реальной ширины каждого файла в пикселях. Для этого используется дескриптор w (от слова width):
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
alt="Пейзаж"
>
В этом примере мы предлагаем браузеру три файла шириной 400, 800 и 1600 пикселей. Но этого недостаточно: браузер не знает, какого размера будет изображение на странице. Оно может занимать всю ширину экрана, а может быть встроено в узкую колонку блога. Здесь на помощь приходит атрибут sizes:
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
alt="Пейзаж"
>
Атрибут sizes подсказывает браузеру, сколько места (в CSS-пикселях) будет занимать изображение при разных условиях. В данном примере логика такая:
- если ширина окна браузера меньше или равна 600 пикселям, изображение занимает 100% ширины окна (
100vw); - если ширина окна от 601 до 1200 пикселей — 50% ширины окна (
50vw); - во всех остальных случаях — 800 пикселей.
Теперь браузер может принять решение. Допустим, пользователь заходит с мобильного устройства, ширина экрана которого 375 пикселей. Браузер смотрит в sizes, видит условие (max-width: 600px) и понимает, что изображение займёт 100vw, то есть 375 CSS-пикселей. Затем он обращается к srcset, находит файл с шириной 400w (ближайший больший к 375) и загружает photo-400.jpg. Всё, что нужно, и ничего лишнего.
srcset + sizesЕсли бы мы не указали sizes, браузер по умолчанию принял бы, что изображение занимает 100vw при любых условиях, и мог бы выбрать файл 800w или даже 1600w для мобильного устройства — просто потому, что у него нет информации о реальном размере изображения на странице.
Когда размер отображения фиксирован
Бывают случаи, когда вы точно знаете, что изображение всегда будет отображаться в одном и том же размере независимо от ширины экрана. Например, аватарка пользователя, иконка или логотип, которому в CSS задана фиксированная ширина 200 пикселей. В такой ситуации можно использовать упрощённый синтаксис с дескрипторами плотности пикселей x:
<img
src="avatar-200.jpg"
srcset="avatar-200.jpg 1x, avatar-400.jpg 2x, avatar-600.jpg 3x"
width="200"
height="200"
alt="Аватар пользователя"
>
Здесь 1x, 2x, 3x обозначают плотность пикселей экрана. На устройстве с обычным экраном (1x) загрузится avatar-200.jpg. На Retina-дисплее (2x) — avatar-400.jpg, который будет отображаться чётче. Атрибут sizes в этом случае не нужен, потому что браузер уже знает итоговый размер отображения из CSS или атрибутов width/height.
Важное замечание о совместимости
Старые браузеры, которые не поддерживают srcset и sizes, просто игнорируют эти атрибуты и загружают изображение из src. Поэтому важно всегда указывать src как резервный вариант — он будет использоваться и в старых браузерах, и в современных как значение по умолчанию (например, если по какой-то причине ни один кандидат из srcset не подошёл).
Техника адаптивных изображений решает проблему не только трафика, но и визуального качества. Когда вы отдаёте браузеру право выбора, он может учитывать не только размер экрана, но и другие факторы: пропускную способность сети, настройки пользователя, возможности устройства. Это делает ваш сайт более гибким и отзывчивым к реальным условиям использования.
Современные форматы и элемент <picture>
Форматы JPEG и PNG, которые десятилетиями служили основой веб-графики, постепенно уступают место более эффективным решениям. AVIF и WebP обеспечивают значительно лучшее сжатие при том же визуальном качестве — файлы могут быть на 25–50% легче по сравнению с JPEG и на 30–70% легче по сравнению с PNG. Это напрямую влияет на скорость загрузки страниц и экономию трафика пользователей.
Однако есть проблема: поддержка современных форматов не универсальна. AVIF, например, не работает в Internet Explorer и в некоторых старых версиях Safari, а WebP хоть и поддерживается всеми современными браузерами, но может отсутствовать в очень старых окружениях. Нам нужно решение, которое позволит предлагать современные форматы там, где они поддерживаются, и откатываться к проверенным JPEG или PNG там, где нет.
Эту задачу решает элемент <picture>. Он работает как контейнер, внутри которого браузер последовательно проверяет элементы <source> и выбирает первый подходящий ресурс. Если ни один не подошёл, в дело вступает резервный <img>.
<picture>Вот как выглядит базовая конструкция для поддержки AVIF, WebP и JPEG:
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" alt="Описание изображения">
</picture>
Браузер просматривает <source> сверху вниз. Для каждого он проверяет значение атрибута type: если указанный MIME-тип поддерживается, браузер загружает изображение из srcset и останавливается. Если не поддерживается — переходит к следующему. В результате:
- браузеры с поддержкой AVIF получат самый лёгкий файл;
- браузеры без AVIF, но с WebP — получат WebP;
- браузеры, не поддерживающие ни AVIF, ни WebP, — получат JPEG из резервного
<img>.
Атрибут type здесь играет ключевую роль: он позволяет браузеру отсечь неподдерживаемые форматы ещё до того, как начнётся загрузка. Без type браузеру пришлось бы скачать файл, чтобы понять, может ли он его отобразить, — что сводит на нет весь смысл оптимизации.
Комбинация с адаптивностью
Элемент <picture> не отменяет необходимость адаптивных изображений. Напротив, эти техники прекрасно сочетаются: внутри <source> можно использовать srcset и sizes точно так же, как в обычном <img>. Это позволяет браузеру выбирать не только формат, но и оптимальный размер файла для текущего экрана.
<picture>
<source
type="image/avif"
srcset="photo-400.avif 400w, photo-800.avif 800w, photo-1600.avif 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
>
<source
type="image/webp"
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
>
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 50vw"
alt="Описание изображения"
>
</picture>
В этом примере браузер сначала выбирает поддерживаемый формат, а затем внутри выбранного <source> (или внутри резервного <img>) применяет механику srcset/sizes для определения нужного размера. Такой код даёт браузеру максимальную гибкость: он может выбрать и лучший формат, и оптимальный размер, исходя из возможностей устройства и условий просмотра.
Когда использовать <picture>, а когда достаточно srcset
Универсального правила «всегда использовать <picture>» не существует. Если ваше изображение одинаково выглядит во всех форматах и единственная цель — уменьшить вес файла, достаточно srcset с разными размерами. <picture> нужен в двух случаях:
- когда вы хотите предложить разные форматы файлов (AVIF, WebP) с резервным вариантом;
- когда требуется художественное оформление — то есть не просто разные размеры, а визуально разные изображения для разных экранов (например, широкий пейзаж для десктопа и его обрезанная версия с крупным планом для мобильного устройства). В последнем случае в
<source>добавляется атрибутmediaс медиавыражением, который переопределяет выбор на основе ширины экрана.
Следует помнить, что элемент <picture> не является самостоятельным — он всегда требует вложенный <img> в качестве резерва. Именно этот <img> будет использоваться, если ни одно из условий не сработает, а также в старых браузерах, не поддерживающих <picture>.
Управление загрузкой: атрибуты loading, decoding и fetchpriority
Когда браузер встречает тег <img>, ему нужно решить три вопроса: когда начать загрузку файла, как его обрабатывать после загрузки и насколько он важен по сравнению с другими ресурсами страницы. Три атрибута — loading, decoding и fetchpriority — дают разработчику возможность влиять на эти решения. В отличие от srcset или <picture>, которые влияют на то, какое изображение загружается, эти атрибуты управляют процессом загрузки и отображения.
loading: отложенная загрузка
Атрибут loading определяет, должен ли браузер загружать изображение немедленно или дождаться момента, когда оно понадобится.
loading="eager"(значение по умолчанию) — изображение загружается сразу, как только браузер доходит до него в HTML, независимо от того, находится оно в видимой области или нет.loading="lazy"— изображение загружается только тогда, когда оно оказывается близко к видимой области (обычно браузер начинает загрузку, когда пользователь прокрутил страницу до расстояния в несколько экранов до изображения).
Применение loading="lazy" ко всем изображениям, которые не видны при первой загрузке страницы, даёт значительный выигрыш: браузер не тратит ресурсы сети и процессора на то, что пользователь, возможно, никогда не увидит. Особенно это важно на длинных страницах с большим количеством контента — галереях, лентах товаров, блогах с длинными статьями.
Однако для изображений, которые находятся в видимой области при загрузке страницы (особенно для LCP-изображения), отложенная загрузка не нужна. Более того, использование loading="lazy" для LCP может ухудшить метрику, так как браузер отложит загрузку важного ресурса. В таких случаях достаточно опустить атрибут или явно указать loading="eager".
decoding: контроль над декодированием
После того как изображение загружено, браузер должен декодировать его — преобразовать сжатые данные (JPEG, WebP, AVIF) в необработанные пиксели, которые можно отобразить на экране. Декодирование выполняется в основном потоке браузера и может блокировать другие важные операции: рендеринг страницы, выполнение JavaScript, обработку пользовательских событий.
Атрибут decoding подсказывает браузеру, как приоритезировать эту операцию:
decoding="async"— разрешает браузеру декодировать изображение параллельно с другими задачами, не блокируя рендеринг. Это хороший выбор для большинства изображений, особенно тех, что находятся за пределами экрана или не являются критическими для первого впечатления.decoding="sync"— декодирует изображение синхронно, что может задержать отображение другого контента. Используется редко, в основном для LCP-изображений, если требуется гарантировать их появление как можно раньше после загрузки.decoding="auto"(по умолчанию) — браузер сам решает, исходя из своих внутренних эвристик.
Практическая рекомендация: для всех изображений, кроме LCP, используйте decoding="async". Для LCP можно оставить auto или указать sync, если вы готовы к возможной задержке остального контента.
fetchpriority: приоритет загрузки
Современные браузеры загружают множество ресурсов одновременно, но ресурсы сети ограничены. Браузеру нужно решать, какие ресурсы загружать в первую очередь. Обычно он хорошо справляется с этим сам: документ HTML загружается первым, затем CSS и шрифты, затем изображения и скрипты. Но бывают ситуации, когда автоматическая эвристика ошибается.
Атрибут fetchpriority позволяет разработчику подсказать браузеру важность ресурса:
fetchpriority="high"— повышает приоритет загрузки. Полезно для LCP-изображений, особенно если они находятся глубоко в HTML (например, внутри карусели или компонента, который подгружается позже).fetchpriority="low"— понижает приоритет. Используется для изображений, которые могут подождать: декоративные фоны, изображения в футере, элементы, которые точно не видны на первом экране.fetchpriority="auto"(по умолчанию) — браузер принимает решение самостоятельно.
Важно понимать, что fetchpriority влияет на очередь загрузки, но не на момент обнаружения ресурса. Если браузер ещё не дошёл до тега <img> в HTML (например, изображение добавляется динамически или находится очень глубоко в документе), fetchpriority="high" не ускорит его появление — браузер просто не знает о его существовании. Эта особенность приводит нас к следующему разделу, где мы рассмотрим, как комбинировать эти атрибуты с предварительной загрузкой для достижения наилучшего результата.
Стратегия для LCP: предварительная загрузка и комбинирование атрибутов
Largest Contentful Paint (LCP) — одна из трёх ключевых метрик Core Web Vitals. Она измеряет время от начала загрузки страницы до момента, когда отрисован самый большой элемент в видимой области. Чаще всего этим элементом оказывается изображение: баннер, крупная иллюстрация. Оптимизация LCP требует особого внимания, потому что даже если все остальные изображения загружаются идеально, медленное появление главного изображения портит пользовательское впечатление.
Из предыдущих разделов мы уже знаем, как указать размеры (чтобы избежать смещения макета), как выбрать правильный формат и размер через srcset и <picture>, как управлять приоритетом через fetchpriority. Но этих мер может оказаться недостаточно. Дело в том, что все эти атрибуты начинают работать только после того, как браузер обнаружит тег <img> в HTML. Если изображение находится глубоко в документе, внутри компонента, который подгружается асинхронно, или в карусели, браузер может узнать о нём слишком поздно. К тому моменту, как парсер дойдёт до <img>, драгоценное время уже будет потеряно.
Здесь на помощь приходит предварительная загрузка — механизм, позволяющий браузеру начать загрузку критического ресурса ещё до того, как он встретится в основном HTML.
Базовый подход: preload в <head>
Добавьте в <head> документа тег <link rel="preload">, указав тип ресурса и его URL. Это заставит браузер начать загрузку изображения немедленно, параллельно с обработкой HTML и других критических ресурсов.
<!-- В <head> -->
<link rel="preload" as="image" href="hero.jpg" fetchpriority="high">
<!-- В <body> -->
<img src="hero.jpg" alt="Главное изображение" width="1200" height="600">
Атрибут as="image" сообщает браузеру тип ресурса, что позволяет ему правильно настроить приоритеты и кэширование. Добавление fetchpriority="high" в тег preload дополнительно подчёркивает важность.
Расширенный подход: предзагрузка адаптивных изображений
Если ваше LCP-изображение использует srcset и sizes (как это часто бывает для героев страниц, которые должны хорошо выглядеть на любых экранах), обычный preload не подойдёт — браузер не будет знать, какой именно вариант из srcset загружать. В этом случае используются специальные атрибуты imagesrcset и imagesizes внутри preload.
<link
rel="preload"
as="image"
imagesrcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
imagesizes="(max-width: 600px) 100vw, 800px"
fetchpriority="high"
>
Браузер получает ту же информацию, что и из srcset/sizes в <img>, и может предварительно загрузить именно ту версию, которая подойдёт для текущего устройства.
Комбинация с <picture> и современными форматами
Если LCP-изображение использует <picture> для поддержки AVIF и WebP, preload тоже работает, но требует указания типа. Для этого можно добавить атрибут type и, если нужно, отдельные preload для разных форматов, хотя браузер всё равно загрузит только один из них.
<link
rel="preload"
as="image"
imagesrcset="hero-800.avif 800w, hero-1600.avif 1600w"
imagesizes="(max-width: 600px) 100vw, 800px"
type="image/avif"
fetchpriority="high"
>
Браузер проверит, поддерживает ли он AVIF. Если да — предварительно загрузит указанный вариант. Если нет — проигнорирует этот preload, и загрузка пойдёт по обычному пути через <picture>. Для надёжности можно добавить несколько preload с разными type, но это увеличивает объём разметки; обычно достаточно одного preload для наиболее современного формата.
Собираем всё вместе
Для LCP-изображения оптимальная стратегия выглядит так:
- Добавить
<link rel="preload">в<head>сimagesrcset,imagesizesиfetchpriority="high", чтобы начать загрузку как можно раньше. - В основном HTML разместить
<picture>или<img>с полным набором атрибутов:srcset/sizesдля адаптивности,width/heightдля резервирования места,loading="eager"(или просто опустить атрибут),decoding="sync"для ускорения рендеринга,fetchpriority="high"для усиления приоритета. - Если используется
<picture>, убедиться, что порядок<source>соответствует убыванию качества формата (AVIF → WebP → JPEG), чтобы браузер останавливался на самом эффективном из поддерживаемых.
Полный пример для изображения с поддержкой AVIF, WebP, адаптивными размерами и предзагрузкой:
<!-- В <head> -->
<link
rel="preload"
as="image"
imagesrcset="hero-400.avif 400w, hero-800.avif 800w, hero-1600.avif 1600w"
imagesizes="(max-width: 600px) 100vw, 800px"
type="image/avif"
fetchpriority="high"
>
<!-- В <body> -->
<picture>
<source
type="image/avif"
srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1600.avif 1600w"
sizes="(max-width: 600px) 100vw, 800px"
>
<source
type="image/webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1600.webp 1600w"
sizes="(max-width: 600px) 100vw, 800px"
>
<img
src="hero-800.jpg"
srcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, 800px"
width="1600"
height="900"
alt="Главное изображение"
loading="eager"
decoding="sync"
fetchpriority="high"
>
</picture>
Приведённая ниже схема визуализирует эту двухэтапную стратегию.
Эта конструкция даёт браузеру максимум информации на самом раннем этапе и позволяет загрузить и отобразить критическое изображение с минимальной задержкой.
Детальная механика предзагрузки адаптивных изображений, включая тонкости работы imagesrcset и imagesizes в разных браузерах, подробно разобрана в отдельной статье — «Предзагрузка отзывчивых изображений». Если хотите углубиться в нюансы этого механизма, рекомендую обратиться к ней.
Семантическая обёртка: <figure> и <figcaption> в сочетании с <picture>
Все предыдущие разделы были посвящены техническим аспектам: как загрузить изображение, как выбрать правильный размер и формат, как ускорить его появление. Но изображение в вебе — это не только файл и его атрибуты. Часто оно является самостоятельной единицей контента: диаграммой, иллюстрацией к статье, скриншотом интерфейса, фотографией с подписью. В таких случаях важно не только то, как изображение загружается, но и то, как оно представлено в структуре документа.
Элементы <figure> и <figcaption> дают возможность создать семантическую связь между изображением и его описанием. Они не влияют на производительность, не меняют поведение загрузки и не взаимодействуют с атрибутами вроде srcset или loading. Но они улучшают доступность, помогают поисковым системам правильно интерпретировать контент и делают код более осмысленным.
Элемент <figure> служит контейнером для самодостаточного контента. Внутри него может быть изображение, видео, диаграмма, фрагмент кода или даже цитата — всё, что является самостоятельной единицей и может быть перенесено в другую часть страницы без потери смысла.
Элемент <figcaption> добавляет подпись (или заголовок) к этому контенту. Он может быть первым или последним потомком <figure> — порядок зависит от того, хотите ли вы, чтобы подпись предваряла изображение или следовала за ним.
<figure>
<img src="schema.png" alt="Схема работы браузера с изображениями">
<figcaption>Рис. 1. Как браузер обрабатывает изображение: от обнаружения в HTML до отрисовки на экране</figcaption>
</figure>
Комбинация с <picture>
Технические возможности, которые мы рассмотрели в предыдущих разделах — адаптивность, современные форматы, предзагрузка — не противоречат семантической обёртке. Напротив, <picture> и <figure> решают разные задачи и прекрасно сочетаются: <picture> управляет тем, какой файл загружается, а <figure> объясняет, что это за изображение и как оно связано с контекстом.
<figure>
<picture>
<source type="image/avif" srcset="schema.avif">
<source type="image/webp" srcset="schema.webp">
<img src="schema.png" alt="Схема работы браузера с изображениями">
</picture>
<figcaption>Рис. 1. Как браузер обрабатывает изображение: от обнаружения в HTML до отрисовки на экране</figcaption>
</figure>
В этом примере <picture> обеспечивает выбор оптимального формата, а <figure> с <figcaption> придают изображению смысловую завершённость.
Когда использовать, а когда нет
Не каждое изображение нуждается в <figure>. Декоративные изображения (фоновые картинки, иконки интерфейса, разделители) не должны быть обёрнуты в <figure> — у них нет самостоятельного значения, и они не требуют подписи. Атрибута alt="" (пустой) для них достаточно, чтобы скринридеры игнорировали их.
А вот для иллюстраций, диаграмм, графиков, скриншотов с пояснениями, фотографий в галереях, обложек статей (если они сопровождаются подписью) использование <figure> является лучшей практикой. Это даёт чёткий сигнал браузеру, поисковым системам и вспомогательным технологиям, что перед ними — законченная смысловая единица.
Связь с доступностью
Важно понимать разницу между атрибутом alt и элементом <figcaption>. alt предоставляет краткое текстовое описание изображения для случаев, когда само изображение недоступно (проблемы с загрузкой, скринридеры, текстовые браузеры). <figcaption> — это видимая подпись, которая сопровождает изображение и доступна всем пользователям.
Если вы используете <figure> с <figcaption>, это не отменяет необходимости в alt. Содержимое alt и <figcaption> могут пересекаться, но обычно решают разные задачи: alt — функциональное описание, <figcaption> — контекстное пояснение.
Вопросы доступности изображений и различия между alt и <figcaption> подробно разобраны в статье «Атрибут alt и figcaption: в чём разница и что использовать» . Для глубокого понимания этой темы рекомендую обратиться к ней.
Прагматичный путь: использование Image CDN
К этому моменту мы разобрали все ключевые техники работы с изображениями: управление внутренним размером, адаптивность через srcset и sizes, поддержку современных форматов через <picture>, тонкую настройку загрузки атрибутами loading, decoding, fetchpriority, стратегию для LCP с предварительной загрузкой и семантическую обёртку через <figure>.
Если применить всё это вручную к каждому изображению на сайте, код получится безупречным с технической точки зрения. Но есть одна проблема: поддержка такого подхода требует значительных усилий. Для каждого изображения нужно создать несколько версий в разных размерах, сконвертировать их в AVIF, WebP и JPEG, прописать корректные srcset и sizes, не забыть про preload для критических изображений. На большом проекте с сотнями или тысячами изображений это становится трудоёмкой задачей, которую легко ошибиться и сложно поддерживать.
Здесь на помощь приходят Image CDN — специализированные сервисы, которые автоматизируют практически все описанные выше задачи.
Что такое Image CDN и как это работает
Image CDN (Cloudinary, Imgix, Cloudflare Images, Fastly Image Optimizer и другие) — это сервисы, которые принимают исходное изображение, оптимизируют его на лету и доставляют через сеть доставки контента (CDN) с ближайшего к пользователю сервера.
Вместо того чтобы создавать десятки вариантов одного изображения, вы загружаете один исходный файл (например, photo.jpg). Затем в URL вы указываете параметры преобразования: нужную ширину, качество, формат. CDN генерирует подходящую версию в момент запроса и кэширует её для следующих обращений.
<img
src="https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_800/photo.jpg"
width="800"
height="600"
alt="Описание"
loading="lazy"
decoding="async"
>
Разберём параметры в этом URL:
f_auto— говорит Cloudinary автоматически выбрать оптимальный формат (AVIF, WebP или JPEG) на основе заголовковAcceptбраузера. Это полностью заменяет ручную работу с<picture>.q_auto— автоматически подбирает уровень сжатия, балансируя между качеством и размером файла.w_800— задаёт ширину изображения. CDN сгенерирует именно этот размер.
Для адаптивных изображений можно комбинировать srcset с CDN-URL, генерируя разные размеры через параметры в ссылке:
<img
src="https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_800/photo.jpg"
srcset="
https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_400/photo.jpg 400w,
https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_800/photo.jpg 800w,
https://res.cloudinary.com/demo/image/upload/f_auto,q_auto,w_1600/photo.jpg 1600w
"
sizes="(max-width: 600px) 100vw, 50vw"
width="1600"
height="900"
alt="Описание"
>
При этом все преобразования происходят автоматически — вам не нужно хранить десятки файлов на сервере и поддерживать их актуальность.
Преимущества и компромиссы
Преимущества Image CDN:
- Упрощение рабочего процесса — не нужно создавать и поддерживать множество версий изображений.
- Автоматический выбор формата — CDN сам определяет, поддерживает ли браузер AVIF или WebP.
- Оптимизация качества — алгоритмы подбирают баланс между размером файла и видимым качеством.
- Глобальная доставка — изображения отдаются с ближайшего к пользователю сервера, что снижает задержки.
- Единая точка управления — можно менять параметры оптимизации глобально, не пересобирая сайт.
Компромиссы, которые стоит учитывать:
- Зависимость от внешнего сервиса — если CDN недоступен, изображения не загрузятся (хотя у крупных провайдеров надёжность близка к 99,99%).
- Дополнительные расходы — большинство Image CDN имеют бесплатные тарифы с ограничениями и платные для больших объёмов.
- Меньше контроля — вы полагаетесь на алгоритмы CDN в вопросах выбора формата и степени сжатия.
Когда выбирать ручное управление, а когда CDN
Ручное управление (создание всех версий вручную, прописывание srcset, <picture>, preload) даёт максимальный контроль и не требует зависимости от внешних сервисов. Оно имеет смысл, если:
- вы работаете в строго контролируемой среде без доступа к внешним API;
- изображения имеют специфические требования к качеству или форматам, которые CDN не может гарантировать;
- проект небольшой, и поддержка ручного подхода не требует значительных затрат.
Image CDN — это прагматичный выбор для большинства проектов, особенно если:
- на сайте сотни или тысячи изображений;
- команда не хочет тратить время на ручную оптимизацию и поддержку множества версий;
- важна максимальная скорость загрузки для пользователей по всему миру;
- вы используете систему управления контентом (CMS), которая может интегрироваться с CDN напрямую.
Важно понимать, что выбор CDN не отменяет необходимости знать те принципы, которые мы разобрали в этой статье. Понимание того, как работают srcset, sizes, внутренний размер и приоритеты загрузки, помогает правильно настроить CDN и диагностировать проблемы, даже если вы не пишете эти атрибуты вручную. CDN автоматизирует реализацию, но не отменяет ответственность разработчика за понимание процесса.
Заключение
Мы прошли путь от базового понимания того, как браузер видит изображение, до сложных стратегий оптимизации LCP и выбора между ручным управлением и Image CDN. На этом пути мы выяснили несколько ключевых принципов, которые стоит унести с собой.
Указание width и height в HTML — это не архаизм и не лишняя работа. Это единственный надёжный способ избежать смещения макета и дать браузеру возможность зарезервировать место заранее.
Адаптивные изображения через srcset и sizes — это не просто способ сэкономить трафик. Это возможность предложить браузеру выбор, который он может сделать с учётом реальных условий: размера экрана, плотности пикселей, пропускной способности сети. Отказ от sizes лишает браузер этой возможности.
Современные форматы AVIF и WebP — это самый простой способ уменьшить вес изображений без потери качества. Элемент <picture> делает их использование безопасным, сохраняя совместимость со старыми браузерами.
Атрибуты loading, decoding и fetchpriority позволяют управлять процессом загрузки с точностью, которая раньше требовала сложных JavaScript-решений. loading="lazy" для изображений вне экрана, decoding="async" для большинства случаев и fetchpriority="high" для LCP — это простые правила, которые дают измеримый результат.
Для LCP-изображения одной только правильной разметки недостаточно. Предварительная загрузка через <link rel="preload"> с imagesrcset и imagesizes решает проблему позднего обнаружения и позволяет начать загрузку критического ресурса на максимально раннем этапе.
Семантическая обёртка через <figure> и <figcaption> завершает картину, превращая технически безупречное изображение в осмысленную часть документа. Это особенно важно для контентных проектов, где изображения несут самостоятельную ценность.
И наконец, Image CDN предлагает путь, который объединяет все эти техники в автоматизированном решении. Это не отмена изученных принципов, а их прагматичное применение в масштабе.
Каждый из описанных подходов сам по себе даёт небольшой выигрыш. Но в сумме они превращают изображения — одни из самых «тяжёлых» элементов страницы — в предсказуемый, производительный и доступный компонент, который работает на пользователя, а не против него. А в мире, где время загрузки страницы напрямую влияет на удержание аудитории и конверсию, это превращается из технической детали в стратегическое преимущество.