Использование адаптивных изображений в HTML
В этой статье мы познакомимся с понятием адаптивных изображений — изображений, которые хорошо отображаются на устройствах с сильно различающимися размерами экрана, разрешением и другими характеристиками, — и рассмотрим средства HTML, помогающие реализовать их. Это позволяет повысить производительность на разных устройствах.
Зачем нужны адаптивные изображения?
Рассмотрим типичный сценарий. На обычном веб-сайте может быть изображение в заголовке и несколько изображений в области содержимого под ним. Изображение заголовка, скорее всего, будет занимать всю ширину заголовка, а изображение содержимого будет размещено где-нибудь внутри колонки с содержимым. Вот пример:
Это хорошо работает на устройствах с широким экраном, например на ноутбуке или настольном компьютере (можно посмотреть работающий пример и найти исходный код на GitHub). В этом уроке мы не будем подробно обсуждать CSS, отметим лишь следующее:
- Для содержимого body задана максимальная ширина 1200 пикселей — в областях просмотра шире этого значения ширина body остаётся равной 1200px и он располагается по центру доступного пространства. В областях просмотра уже этого значения ширина body будет составлять 100% ширины области просмотра.
- Для изображения заголовка задано такое положение, чтобы его центр всегда оставался в центре заголовка независимо от установленной ширины заголовка. Если сайт просматривается на более узком экране, важная деталь в центре изображения (люди) всё ещё будет видна, а лишняя часть изображения обрежется по краям. Высота изображения — 200px.
- Для изображений содержимого задано такое поведение, чтобы они начинали уменьшаться, если элемент body становится уже изображения. Благодаря этому они всегда остаются внутри body, а не выходят за его границы.
Однако при просмотре сайта на устройстве с узким экраном возникают проблемы. Заголовок ниже выглядит нормально, но начинает занимать слишком много места по высоте на экране мобильного устройства. А при таком размере сложно разглядеть лица двух людей на первом изображении содержимого.
Улучшить ситуацию можно, отображая обрезанную версию изображения, в которой видны важные детали, когда сайт просматривают на узком экране. Для устройства со средним размером экрана, например планшета, можно показывать второе обрезанное изображение. Общая задача, при которой для разных макетов требуется предоставлять разные обрезанные изображения, известна как проблема художественного кадрирования.
Кроме того, нет необходимости встраивать на страницу такие большие изображения, если её просматривают на экране мобильного устройства. Это может привести к напрасному расходу трафика; в частности, пользователи мобильных устройств не хотят тратить трафик на загрузку большого изображения, предназначенного для настольных компьютеров, если для их устройства достаточно небольшого. И наоборот, небольшое растровое изображение начинает выглядеть зернистым, если его отображать в размере, превышающем исходный (растровое изображение имеет фиксированное количество пикселей по ширине и высоте). В идеале веб-браузеру пользователя следует предоставить изображения в нескольких разрешениях. Тогда браузер сможет определить оптимальное разрешение для загрузки с учётом размера экрана устройства пользователя. Это называется проблемой переключения разрешений.
Ситуация усложняется тем, что некоторые устройства оснащены экранами с высоким разрешением, которым для качественного отображения нужны изображения большего размера, чем можно было бы ожидать. По сути, это та же проблема, но в несколько ином контексте.
Можно подумать, что эти проблемы решат векторные изображения, и в некоторой степени так и есть: они имеют небольшой размер файла и хорошо масштабируются, поэтому по возможности следует использовать именно их. Однако они подходят не для всех типов изображений. Векторные изображения отлично подходят для простой графики, узоров, элементов интерфейса и т. д., но создание векторного изображения с такой же детализацией, как, например, у фотографии, становится очень сложным. Для изображений, подобных приведённым выше, лучше подходят растровые форматы, например JPEG.
Подобной проблемы не существовало в первые годы развития интернета, в начале — середине 90-х: тогда для просмотра веб-страниц использовались только настольные компьютеры и ноутбуки, поэтому разработчики браузеров и авторы спецификаций даже не задумывались о решениях. Технологии адаптивных изображений появились недавно, чтобы решить описанные выше проблемы. Они позволяют предоставить браузеру несколько файлов изображений: либо с одним и тем же содержимым, но с разным количеством пикселей (переключение разрешений), либо разные изображения, подходящие для разных доступных областей (художественное кадрирование).
Примечание: Новые возможности, рассматриваемые в этой статье, — srcset/sizes/<picture> — поддерживаются во всех современных настольных и мобильных браузерах.
Как создавать адаптивные изображения?
В этом разделе мы рассмотрим две описанные выше проблемы и покажем, как решить их с помощью возможностей HTML для адаптивных изображений. Обратите внимание, что в этом разделе мы сосредоточимся на элементах <img>, как в области содержимого приведённого выше примера. Изображение в заголовке сайта служит только для оформления, поэтому оно реализовано с помощью фоновых изображений CSS. В CSS, пожалуй, есть более подходящие инструменты для адаптивного дизайна, чем в HTML, и мы обсудим их в будущем модуле по CSS.
Переключение разрешений: разные размеры
Итак, какую проблему мы хотим решить с помощью переключения разрешений? Нам нужно отображать одно и то же содержимое изображения, но большего или меньшего размера в зависимости от устройства. Именно такая ситуация возникает со вторым изображением содержимого в нашем примере. Стандартный элемент <img> традиционно позволяет указать браузеру только один исходный файл:
<img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy" />
Однако мы можем использовать два атрибута — srcset и sizes — чтобы указать несколько дополнительных исходных изображений и подсказать браузеру, какое из них выбрать. Пример можно посмотреть в файле responsive.html на GitHub (см. также исходный код):
<img
srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w"
sizes="(width <= 600px) 480px,
800px"
src="elva-fairy-800w.jpg"
alt="Elva dressed as a fairy" />
Атрибуты srcset и sizes выглядят сложными, но их не так трудно понять, если отформатировать их, как показано выше, разместив отдельную часть значения атрибута на каждой строке. Каждое значение содержит список, элементы которого разделены запятыми, а каждый элемент такого списка состоит из трёх частей. Давайте разберём их по порядку:
srcset задаёт набор изображений, из которых браузер сможет выбрать подходящее, и размер каждого изображения. Информация о каждом изображении отделяется от предыдущей запятой. Для каждого изображения указываются:
- Имя файла изображения (
elva-fairy-480w.jpg) - Пробел
- Исходная ширина изображения в пикселях (
480w) — обратите внимание, что здесь используется единицаw, а неpx, как можно было бы ожидать. Исходный размер изображения — его фактический размер, который можно узнать, изучив файл изображения на компьютере (например, на Mac можно выбрать изображение в Finder и нажать Cmd + I, чтобы открыть окно с информацией).
sizes задаёт набор медиавыражений (например, ширину экрана) и указывает, какой размер изображения лучше выбрать при выполнении определённых медиавыражений. Это те подсказки, о которых мы говорили ранее. В этом случае перед каждой запятой указываются:
- Медиавыражение (
(width <= 600px)) — подробнее о них вы узнаете в разделе о CSS, а пока достаточно сказать, что медиавыражение описывает возможное состояние экрана. В данном случае мы указываем: «когда ширина области просмотра не превышает 600 пикселей». - Пробел
- Ширина слота, который займёт изображение, если медиавыражение истинно (
480px)
Примечание: В sizes можно использовать любое значение длины. Например, вместо абсолютной ширины (например, 480px) можно указать ширину относительно области просмотра (например, 50vw). Однако в качестве ширины слота нельзя использовать процентное значение. Возможно, вы заметили, что для последней ширины слота медиавыражение не задано (это значение по умолчанию, которое выбирается, если ни одно из медиавыражений не истинно). Браузер игнорирует всё, что указано после первого совпавшего условия, поэтому внимательно следите за порядком медиавыражений.
Таким образом, с этими атрибутами браузер:
- Проверит размер экрана, плотность пикселей, масштаб, ориентацию экрана и скорость сети.
- Определит первое истинное медиавыражение в списке
sizes. - Определит размер слота, заданный для этого медиавыражения.
- Загрузит изображение из списка
srcset, размер которого совпадает с размером слота. Если точного совпадения с размером области отображения нет, браузер выберет первое изображение, которое больше выбранного размера слота, и уменьшит его, чтобы оно поместилось.
Вот и всё! Если браузер с поддержкой этой возможности загрузит страницу в области просмотра шириной 480px, медиавыражение (width <= 600px) будет истинным, поэтому браузер выберет слот 480px. Будет загружено изображение elva-fairy-480w.jpg, поскольку его исходная ширина (480w) наиболее близка к размеру слота. Изображение шириной 800px занимает на диске 128KB, тогда как версия шириной 480px — всего 63KB. Экономия составляет 65KB. А теперь представьте, что на странице много изображений. Этот метод позволяет значительно сократить расход трафика для пользователей мобильных устройств.
Примечание: Если вы проверяете это в настольном браузере и он не загружает изображения меньшей ширины, когда окно сужено до минимума, проверьте ширину области просмотра (её можно примерно определить, введя document.querySelector('html').clientWidth в консоли JavaScript браузера). У разных браузеров есть минимальные размеры окна, до которых его можно уменьшить, и они могут оказаться больше, чем вы ожидали. При проверке в мобильном браузере можно воспользоваться такими инструментами, как страница about:debugging в Firefox, чтобы просмотреть страницу, загруженную на мобильном устройстве, с помощью инструментов разработчика на настольном компьютере.
Чтобы узнать, какие изображения были загружены, воспользуйтесь вкладкой Монитор сети в Firefox DevTools или панелью Network в Chrome DevTools. В Chrome можно также отключить кэш, чтобы браузер не выбирал уже загруженные изображения.
Старые браузеры, не поддерживающие эти возможности, просто проигнорируют их. Вместо этого они, как обычно, загрузят изображение, указанное в атрибуте src.
Примечание: В элементе <head> приведённого выше примера вы найдёте строку <meta name="viewport" content="width=device-width">: она заставляет мобильные браузеры использовать фактическую ширину области просмотра при загрузке веб-страниц (некоторые мобильные браузеры неверно указывают ширину области просмотра и вместо этого загружают страницы с большей шириной, а затем уменьшают их. Это не очень полезно для адаптивных изображений и дизайна).
Переключение разрешений: одинаковый размер, разное разрешение
Предположим, у вас есть изображение, которое будет отображаться в одном и том же физическом размере на экранах с разным разрешением. На экранах с высоким разрешением можно улучшить взаимодействие с пользователем, предоставляя версию изображения с более высоким разрешением.
Для этого можно позволить браузеру выбрать изображение с подходящим разрешением, используя srcset с дескрипторами x и без sizes — синтаксис здесь несколько проще! Пример можно найти в файле srcset-resolutions.html (см. также исходный код):
<img srcset="elva-fairy-320w.jpg, elva-fairy-480w.jpg 1.5x, elva-fairy-640w.jpg 2x" src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy" />
Обратите внимание: хотя изображение всегда отображается в одном размере, на экранах с более высоким разрешением видно больше деталей.
В этом примере к изображению применяются следующие правила CSS, чтобы его ширина на экране составляла 320 пикселей (также называемых CSS-пикселями):
img {
width: 320px;
}
В этом случае sizes не нужен: браузер определяет разрешение экрана, на котором отображается страница, и выбирает наиболее подходящее изображение из указанных в srcset. Поэтому, если на устройстве, с которого открывают страницу, экран стандартного или низкого разрешения, где одному CSS-пикселю соответствует один пиксель устройства, будет загружено изображение elva-fairy-320w.jpg (значение 1x подразумевается, поэтому указывать его не нужно). Если у устройства высокое разрешение — два пикселя устройства или больше на один CSS-пиксель, будет загружено изображение elva-fairy-640w.jpg. Изображение размером 640px занимает 93KB, а изображение размером 320px — всего 39KB.
Художественное кадрирование
Напомним, что проблема художественного кадрирования заключается в необходимости менять отображаемое изображение в зависимости от размера области его отображения. Например, на веб-странице при просмотре в настольном браузере показывается большой альбомный снимок с человеком в центре. При просмотре в мобильном браузере то же изображение уменьшается, из-за чего человек на нём становится очень маленьким и его трудно разглядеть. На мобильных устройствах, вероятно, лучше показывать более маленькое портретное изображение, на котором человек крупнее. Элемент <picture> позволяет реализовать именно такое решение.
Вернёмся к нашему исходному примеру not-responsive.html: у нас есть изображение, которому очень не хватает художественного кадрирования:
<img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva" />
Исправим это с помощью элемента <picture>! Как и <video> и <audio>, элемент <picture> является обёрткой, содержащей несколько элементов <source>, которые предоставляют браузеру разные источники на выбор, а затем — важный элемент <img>. Код в файле responsive.html выглядит так:
<picture> <source media="(width < 800px)" srcset="elva-480w-close-portrait.jpg" /> <source media="(width >= 800px)" srcset="elva-800w.jpg" /> <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva" /> </picture>
- Элементы
<source>содержат атрибутmediaс медиавыражением. Как и в первом примере сsrcset, эти выражения проверяют, какое изображение следует показать: отображается первое изображение, для которого условие истинно. В данном случае, если ширина области просмотра меньше 800px, будет показано изображение из первого элемента<source>. Если ширина области просмотра составляет 800px или больше, будет показано второе изображение. - Атрибуты
srcsetсодержат путь к отображаемому изображению. Как мы видели выше на примере<img>, элемент<source>может содержать атрибутsrcsetс несколькими указанными изображениями, а также атрибутsizes. Таким образом, можно предложить несколько изображений с помощью элемента<picture>, а также несколько разрешений для каждого из них. На практике, вероятно, такой подход понадобится нечасто. - Во всех случаях непосредственно перед
</picture>необходимо добавить элемент<img>с атрибутамиsrcиalt, иначе изображения не появятся. Он задаёт вариант по умолчанию, который используется, если ни одно из медиавыражений не истинно (в этом примере можно даже удалить второй элемент<source>), а также служит запасным вариантом для браузеров, не поддерживающих элемент<picture>.
Этот код позволяет показывать подходящее изображение как на широких, так и на узких экранах, как показано ниже:
Примечание: Атрибут media следует использовать только для художественного кадрирования. Если вы используете media, не указывайте медиавыражения также в атрибуте sizes.
Почему нельзя просто сделать это с помощью CSS или JavaScript?
Когда браузер начинает загружать страницу, он загружает (предварительно) все изображения до того, как основной анализатор приступит к загрузке и обработке CSS и JavaScript страницы. В целом этот механизм полезен для сокращения времени загрузки страницы, но для адаптивных изображений он не подходит. Поэтому нужны такие решения, как srcset. Например, нельзя загрузить элемент <img>, затем определить ширину области просмотра с помощью JavaScript и динамически заменить исходное изображение на меньшее, если это необходимо. К этому моменту исходное изображение уже будет загружено, и загрузка маленького изображения только усугубит ситуацию с адаптивными изображениями.
Самостоятельная реализация адаптивных изображений
В этом упражнении мы предлагаем вам проявить смелость и по большей части справиться самостоятельно. Вам нужно реализовать подходящий вариант художественного кадрирования для узкого и широкого экрана с помощью <picture>, а также пример переключения разрешений с использованием srcset.
- Напишите HTML-код, в который поместите свой код (при желании можно начать с
not-responsive.html). - Найдите хорошее широкоформатное пейзажное изображение с каким-либо заметным элементом. С помощью графического редактора создайте его версию для веба, затем обрежьте её так, чтобы выделить этот элемент, и создайте второе изображение (подойдёт ширина около 480px).
- Используйте элемент
<picture>для реализации переключения изображений с художественным кадрированием! - Создайте несколько файлов изображений разных размеров, в каждом из которых будет одно и то же изображение.
- Используйте
srcset/sizesдля создания примера переключения разрешений: можно показывать изображение одного размера в разных разрешениях в зависимости от разрешения устройства или изображения разных размеров в зависимости от ширины области просмотра.
Итоги
На этом мы завершаем рассмотрение адаптивных изображений. Надеемся, вам понравилось экспериментировать с новыми методами. Напомним, что мы обсуждали две разные проблемы:
-
Художественное кадрирование: необходимость предоставлять обрезанные изображения для разных макетов — например, пейзажное изображение с полной сценой для настольного компьютера и портретное изображение с увеличенным главным объектом для мобильного устройства. Эту проблему можно решить с помощью элемента
<picture>. -
Переключение разрешений: необходимость предоставлять файлы изображений меньшего размера устройствам с узким экраном, которым не нужны огромные изображения, предназначенные для настольных компьютеров, а также изображения разного разрешения для экранов с высокой и низкой плотностью пикселей. Эту проблему можно решить с помощью векторной графики (изображений SVG) и атрибутов
srcsetиsizes.
См. также
- Изучите: адаптивный дизайн
- Отличное введение в адаптивные изображения от Джейсона Григсби
- Адаптивные изображения: если вы меняете только разрешение, используйте srcset — содержит дополнительные объяснения того, как браузер определяет, какое изображение использовать
<img><picture><source>
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Responsive_images