Srcset html

Адаптивные изображения на сайте: создание с помощью атрибута srcset

От автора: в нашем взаимосвязанном мире, где у людей множество различных устройств, плавность работы веб-сайта на всех устройствах должна быть в приоритете. Число просмотров вашего сайте не складывается только лишь с одного устройства с определенным разрешением. И чтобы сайт хорошо работал с любым разрешением экрана, он должен быть адаптивным.

Если вы слышали про адаптивный веб-дизайн (RWD), то, скорее всего, вы знаете про тонкости, с которыми приходится сталкиваться (и то как Bootstrapрешает их!). Важной составляющей адаптивного сайта являются адаптивные изображения. В этой статье мы узнаем, что такое адаптивные изображения на сайте. Рассмотрим создание адаптивных изображений с помощью атрибута srcset.


Что такое адаптивные изображения?

Простыми словами, адаптивные изображения это изображения, которые отображаются наилучшим образом на различных устройствах. Лучшая форма это:

Адаптивные блоки поддерживаются в большинстве современных браузеров, в том числе в Microsoft Edge (начиная с Windows Insider Build 10547). Поддержку свойства srcset в различных браузерах можно посмотреть здесь.

Как сделать изображения адаптивными

Существует масса способов сделать изображения адаптивными. Один из старых способов – с помощью скрипта (не рекомендуется). Но с ним связаны некоторые проблемы. Первая проблема – если изображение загружается через скрипт, но сам скрипт расположен ниже загружаемого изображения, то можно получить два изображения. Вторая проблема – если в разметке не прописано изображение, и оно загружается только через JS, то есть шанс, что изображение вообще не загрузится, если в браузере отключен JS.

Отсюда вытекает то, что нам нужен лучший способ для создания адаптивных изображений. И к счастью, он существует! В этом методе используются атрибуты: srcset, sizes, picture

Атрибут srcset

Перед тем, как я объясню принцип работы атрибута srcset, важно понять несколько терминов:

Соотношение логических и физических пикселей на устройстве

Соотношение логических и физических пикселей это количество пикселей экрана устройства на один пиксель CSS. Тут есть еще два ключевых термина:


Srcset html

Если приблизить картинку в браузере (Ctrl + Plus), число CSS пикселей для блока DIV не изменится, а вот количество физических пикселей увеличится. Т.е. увеличится число физических пикселей на один CSS пиксель. Если вы хотите отобразить изображение или его часть с помощью метода соотношения логических и физических пикселей, вам понадобится атрибут srcset:

Дескриптор X в атрибуте srcset задает соотношение логических и физических пикселей.

Атрибут src используется для старых браузеров, которые не поддерживают новый атрибут. Данный способ отлично работает. С помощью X Дескриптора вы получите абсолютно такое же изображение на устройствах с одинаковым соотношением логических пикселей к физическим – даже если изображение отображается на 13.5 дюймовом ноутбуке и 5 дюймовом смартфоне.

Теперь предположим, что мы хотим отображать изображение разных размеров на больших и маленьких экранах. Тут нам поможет w дескриптор в атрибуте srcset и новый атрибут sizes. W дескриптор: описывает ширину изображения. Пример:

Из кода следует, что ширина первого изображения 200px, второго 400px, третьего 600px. Если ширина экрана пользователя составляет 150 CSS пикселей, то это приравнивается к X дескриптору:

(Не забывайте, что соотношение логических и физических пикселей это всего лишь количество пикселей устройства на один CSS пиксель)


Атрибут sizes

Если вам нужно отобразить изображение разных размеров (разные высота и ширина) на различных экранах, тут вам поможет атрибут sizes вместе с w дескриптором атрибута srcset. Еще раз рассмотрим пару примеров:

Пример 1

Вы хотите, чтобы изображение занимало половину ширины области просмотра. Код:

Теперь браузер сам решит, какое изображение загрузить, основываясь на ширине окна браузера и соотношении пикселей на устройстве. К примеру: если ширина браузера составляет 500 CSS пикселей, изображение будет занимать 250px в ширину (50vw). То же самое можно получить и таким способом:

Для экранов 1.5x браузер загрузит изображение images/space-needle-2x.jpg, так как соотношение пикселей равно 1.6x (наиболее подходящее для экранов 1.5x).

Пример 2

Вы хотите, чтобы изображение занимало половину ширины области просмотра, если ширина браузера больше 40em. Если ширина браузера равна или меньше 40em, изображение должно занимать всю ширину области просмотра. Код:

Принцип схож с медиа запросами. Если область просмотра в ширину равна 39em, выражение (max-width: 40em) возвращает true, и выполняется 100vw. Изображение занимает всю ширину области просмотра. Т.е. если ширина окна браузера составляет 500 CSS пикселей, то изображение будет 500px в ширину. Того же можно добиться и другим способом:

Похож на первый способ. Браузер определяет, какое изображение больше подходит под заданный размер экрана. Если ширина области просмотра 41em, то выражение (max-width: 40em) обращается в false, и выполняется 50vw. Изображение занимает половину ширины области просмотра. Следующим мы рассмотрим элемент picture, но сначала вспомним все, что мы узнали
:)

Srcset html

Решением последней задачи будет элемент picture!

Тег picture

Как было замечено выше, тег picture используется в тех случаях, когда необходимо отобразить разные изображения под разные размеры экрана. Тег picture представляет собой контейнер для других элементов, с помощью которого можно контролировать загрузку изображений. Рассмотрим пример:

Если в первом source медиа запрос в атрибуте media возвращает true, то при максимальной ширине просмотра в 20em загрузится соответствующее изображение из папки images/small. Все изображения в атрибуте srcset это дубли одного и того же изображения, но под разные разрешения.

Сам по себе тег picture ничего не отображает. Даже тег source отдельно от атрибута srcset ничего не отобразит. Тег source должен содержать атрибут srcset и необязательные атрибуты sizes, media и type. В конце обязательно добавьте внутрь тега picture изображение img.


Выбор подходящего изображения можно делать и по поддерживаемым форматам в браузере. Такой способ отлично подходит, если какой-то формат отлично сохраняет четкость изображения. К примеру, JPEG-XR формат, имеющий меньший вес файла по сравнению с обычным JPG. Поддерживается в Microsoft Edge и IE9+. Протестировать данный формат можно с помощью атрибута type в теге source:

Будет выбрано нужное изображение только при выполнении двух атрибутов media и type. Если браузер не распознает ни один формат, будет взято обычное изображение из тега img.

Собираем все вместе

После осмысления принципа работы адаптивных изображений, рассмотрим заключительный пример, использующий все три способа вместе – srcset, sizes и picture.

В этом примере вы используем тег picture с двумя source. Первый срабатывает, если максимальная ширина области просмотра равна 700px. Далее атрибут sizes решает, какое изображение загрузить в зависимости от размера экрана. Принцип работы ничем не отличается от атрибута sizes. Т.е. если максимальная ширина 500px (от 0px до 500px), изображение займет половину области просмотра. Картинка выбирается в зависимости от соотношения пикселей. Но если ширина области просмотра больше 500px (но <=700px, т.к. мы находимся в первом source), то изображение займет всего 1/10 часть области просмотра.

Схожим образом будет выбран второй source в случае, если максимальная ширина составляет 1400px (т.е. ширина варьируется от 701px до 1400px). Атрибут sizes проверяет область просмотра. Если ее ширина составляет 701px-1000px, изображение займет всю область. Если же ширина находится в пределах 1001px-1400px, то изображение займет половину ширины области просмотра. В качестве проверки всех возможных случаев, я просто изменял размер окна браузера. В реальном мире на ваш сайт будут заходить с различных устройств. Вот именно тогда вы и почувствуете всю мощь адаптивных изображений. Вот что у меня получилось:


Область просмотра окна браузера в пределах от 1001px до 1400px: ширина изображения – половина от размера окна

Srcset html

Область просмотра окна браузера в пределах от 701px до 1000px: ширина изображения – все окно

Srcset html

Область просмотра окна браузера в пределах от 501px до 700px: ширина изображения – 1/10 окна браузера

Srcset html

Область просмотра окна браузера в пределах от 0px до 500px: ширина изображения – половина окна браузера

Srcset html

webformyself.com

Элемент <picture>


Элемент <picture> предлагает декларативный подход к загрузке изображений. Веб-разработчикам больше не нужно будет колдовать с CSS или JavaScript для обработки изображений в адаптивном дизайне. А пользователи получают выгоду от изначально оптимизированных изображений — это особенно важно для пользователей с медленным мобильным интернет-соединением.

Наряду с новыми атрибутами srcset и sizes, недавно добавленными в <img>, элемент <picture> дает веб-разработчикам больше гибкости в указании источников загрузки изображений.

Создайте четкую HTML-разметку и позвольте браузеру самому делать всю работу по обнаружению одного из описанных ниже сценариев (одного сценария или комбинации нескольких), чтобы поддерживать адаптивные конструкции и уменьшить время загрузки веб-страницы.

Выбор на основе ориентации экрана устройства

Мобильное устройство пользователя имеет в данный момент портретную ориентацию или это широкоформатный монитор стационарного компьютера? Загружается изображение, оптимизированное под эти параметры экрана.

Выбор на основе расширения экрана в пикселях

Устройство имеет экран с высоким разрешением? Загружается изображение с высшим разрешением.

Выбор на основе параметров окна

Изображение предполагает определенные пропорции, привязанные к параметрам окна?


Загружается изображение, связанное с параметрами окна.

Выбор на основе формата изображения

Браузер поддерживает дополнительные типы файлов изображений, которые дают прирост производительности, например, меньший размер файла? Загружается альтернативный файл изображения, например, WebP.

Использование ориентации экрана

Наиболее применим элемент <picture> в адаптивном дизайне для «ориентации экрана«. Вместо того чтобы использовать одно изображение, которое пропорционально масштабируется по высоте или ширине в зависимости от размеров окна просмотра, вы загружаете несколько изображений, которые предназначены для заполнения всей области просмотра при разных параметрах экрана:

Это результат использования одного масштабируемого изображения:

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

Оптимизация производительности источника изображения

При использовании элементов <picture> или <img> с атрибутами srcset и sizes, браузер будет загружать только изображение, четко привязанное к сценарию. Эта реализация совместима с HTML-парсерами и может дать дополнительный эффект при применении с кэшированием изображений браузером и предварительной загрузкой.

Просмотр интерактивных демонстраций

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


Откройте демо в новой вкладке в Google Chrome 38 или выше. Измените размер окна, чтобы увидеть кота в действии.

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

Синтаксис <picture>

В следующем фрагменте HTML— и CSS-кодов приведено все, что было использовано для реализации данной демонстрации:

Обратите внимание, что здесь не используется ни JavaScript, ни сторонние библиотеки. Блок CSS <style> используется только для стиля элемента изображения и не содержит медиа запросов. Оригинальная реализация элемента <picture> предполагает, что вы можете объявить свои адаптивные изображения, используя только HTML.

Использование вместе с элементом <source>

Элемент <picture> не имеет собственных уникальных атрибутов. Магия происходит, когда <picture> используется в качестве контейнера для элемента <source>.

Элемент <source>, который используется для загрузки медиа, таких как видео или аудио, был обновлен для загрузки изображений, и для него были добавлены следующие новые атрибуты:

srcset (обязательный)

Принимает один путь к файлу изображения (например, srcset=»kitten.png»). Или список путей к файлам изображений через запятую с дескрипторами плотности пикселей (например, srcset=»kitten.png, kitten@2X.png 2x»), где дескриптор 1x принимается по умолчанию, если его значение не указано.


media (необязательный)

Принимает любой валидный медиа запрос, который обычно размещается в CSS селекторе @media (например, media=»(max-width: 30em)»).

Используется тот же синтаксис элемента, что и в предыдущем примере.

sizes (необязательный)

Принимает один дескриптор ширины (например, sizes=»100vw») или один медиа запрос с дескриптором ширины (например, sizes=»(max-width: 30em) 100vw»).

Или список медиа запросов через запятую с дескриптором ширины (например, sizes=»(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw — 100px)»), где последний пункт списка используется в качестве значения по умолчанию.

type (необязательный)

Принимает поддерживаемый тип MIME (например, type=»image/webp» ortype=»image/vnd.ms-photo»).

Браузер будет использовать указания, предоставляемые через значения атрибутов для загрузки наиболее подходящего источника изображения. Порядок расстановки тегов имеет значение! Браузер будет использовать в качестве указания первый элемент <source> и игнорировать все следующие теги <source>.

Добавление окончательного элемента Элемент <img> также был обновлен, чтобы реализовать возможность его использования в элементе <picture> в качестве резервного варианта, если браузер не поддерживает элемент изображения или если отсутствует соответствующий тег источника изображения. Использование <img> в <picture> является обязательным требованием — если вы забудете сделать это, изображения не будут выводиться. Используйте <img> для объявления изображения по умолчанию, которое будет использоваться в блоке <picture>. Элемент <img> должен размещаться, как последний дочерний элемент <picture>, так как браузер будет игнорировать все объявления <source>, которые размещаются после тега <img>. Тег изображения также используется в том месте, где вы должны указать альтернативный текст с помощью атрибута изображения alt. Использование с дескрипторами плотности пикселей

Вы можете добавить поддержку для дисплеев с высоким разрешением, используя дескрипторы плотности пикселей, такие как 1x, 1.5x, 2x и 3x. Новый атрибут srcset применяется и к элементу <img>, и к элементу <source>.

В приведенном ниже примере поддерживается разрешения экранов 1x, 1.5x, и 2x:

Использование с дескрипторами ширины

Основополагающие принципы Веб описывают новые атрибуты размеров для элемента <img> следующим образом:

Ниже приводится пример использования атрибута sizes для установки пропорций изображения таким образом, чтобы оно всегда заполняло 80% видимой области экрана. Он применяется вместе с атрибутом srcset, чтобы предоставить четыре версии одного и того же фото маяка шириной в 160 пикселей, 320 пикселей, 640 пикселей, и 1280 пикселей:

Браузер будет использовать эти указания, чтобы выбрать наиболее подходящий источник изображения для текущей ширины окна браузера и разрешения дисплея устройства:

Например, окно слева имеет приблизительно 800 пикселей в ширину. Браузер загрузит файл lighthouse-640.jpg. Если только соотношение пикселей дисплея устройства не равно 2x — в этом случае будет загружен файл lighthouse-1280.jpg.

Добавив <picture>, вы можете применить атрибут sizes и к элементу <img>, и к элементу <source>:

Основываясь на предыдущем примере, если окно просмотра имеет ширину 800 пикселей и больше, браузер будет обслуживать альбомную версию фотографии маяка:

Ширина области просмотра слева больше 800 пикселей, поэтому отображается альбомная версия фото маяка.

Загрузите альтернативные форматы файлов изображений

Атрибут type элемента <source> может быть использован для загрузки альтернативных форматов файлов изображений, которые не поддерживаются во всех браузерах.

Например, вы можете предоставить изображение в формате WebP для браузеров, которые поддерживают его, в то время как для других браузеров будет использоваться формат JPEG:

www.internet-technologies.ru

A Terrible Solution: Giant Images for Everyone

One way to handle support for high-resolutions screens is to simply serve the biggest image you can all the time.

This almost a good idea. Low-rez and small-size screens can display the giant, high-def image with no problem. They just won’t see any benefit.IT will look basically the same to them as if you had given them an image half the size. So, the user experience improves for the high-end viewers and every one else is unaffected. Great, right?

Hopefully, you can see the problem here. Providing much larger images does not leave everyone else unaffected. They still have to download them. This costs them bandwidth, and it costs you bandwidth. It also slows down their page load times and uses up more of their computer’s memory.

A Better Solution: Serve Different Images to Different Visitors

What you really want to be able to do is serve the largest image that actually makes a difference to each user. If someone can see you high-quality, high-resolution, gigantic image, then you want to serve it to them. But to someone visiting you on a 5-year-old smart phone, you want to give them a smaller image.

Easy right?

The Old Way(s)

The first wave of solutions to this problem involved complex media queries, JavaScript, or server-side image selection. They were difficult to setup, complicated to understand, and somewhat error prone. Worst of all, they required you (well, your system) to figure out which image version to select. This required a lot of guessing, and put the burden of future improvements on your website’s code.

But, thanks to HTML5, we can do all this pretty easily.

The New Way: srcset

Using the srcset attribute has made responsive image sizing much simpler. It allows you to define a list of differently-sized versions of the same image, and provide information about the size of each one. Then, the client (browser) gets to make the decision.

This last part is particularly worth noting, because the client device actually knows what it is capable of, whereas your website code has to make queries and guesses to figure it out. Moreover, browser technology continues to improve, whereas most website designs are on the “set it and forget it” development cycle.

Using srcset

There are two parts to using srcset — creating the individual files, and then the markup.

Individual File Sizes

First, you need to create several different sized versions of the same image. This is slightly different depending on whether you are using photographs and existing artwork or creating new artwork from scratch.

In either case, you’ll usually want to create at least four versions of each image: a “normal” sized one, and then one at twice the size (2x), three times (3x), and four times (4x). When you create your images, it is helpful to append a size specification to each files:

  • image-1x.jpg
  • image-2x.jpg
  • image-3x.jpg
  • image-4x.jpg

This doesn’t make any difference to the browser, but it will your life easier. Also, note that you could create more versions at different size (larger, smaller) and there is no limit to the number of source files specified in the srcset attribute. However, general practice seems to have settled on four sizes (at least for now).

New Artwork

With new artwork, the job is easy. You are probably using something like Adobe Illustrator or Inkscape to create your images. When you export them, simply export them at different sizes. (The naming example above uses .jpg. Don’t forget that most non-photographic artwork looks better with a PNG.)

(As a side note, if you are creating purely vector graphics, and you can export to SVG, you should do that instead and ignore this entire thing. SVG files are infinitely scalable, look great on all screens regardless of resolution, and are now supported in all current browser versions.)

Existing Artwork and Photography

The trick here is to start with the biggest possible image, or — at least — the biggest image you plan to serve up. Then scale it down to each individual version.

  • Largest or original — image-4x.jpg
  • Scaled down to 75% — image-3x.jpg
  • Scaled down to 50% — image-2x.jpg
  • Scaled down to 25% — image-1x.jpg

The Markup

The srcset attribute allows you to specify a list of image file URLs, along with size descriptions. Yo ualso need to still use the src attribute to identify a “default” image source, to be used in browsers that don’t support srcset.

The markup looks likes this:

<img  srcset="  url size,  url size,  url size  "  src="default url" > 

(We know, it seems weird to have an HTML tag take up multiple lines, but it makes it much easier to keep track of.)

In the live examples below, we’ll use the following images:

  • flamingo4x.jpg — 4025 × 2672 — 3.8 MB
  • flamingo3x.jpg — 3019 × 2005 — 3.7 MB
  • flamingo2x.jpg — 2013 × 1337 — 1.9 MB
  • flamingo1x.jpg — 1006 × 668 — 338 KB
  • flamingo-fallback.jpg — 1006 × 668 — 108 KB

Notice the file size difference between 1x and 4x. The 4x version is over 11 times larger. This is why you should not serve the high-quality images to low-resolution screens.

Specifying Image Density

The more common way to to set include size information in the srcset attribute is to label each file by image density. You do this by putting 1x, 2x, 3x and so forth after the URL. This works if you have made the different images in proportion to each other (which we did).

<img  srcset="  /wp-content/uploads/flamingo4x.jpg 4x,  /wp-content/uploads/flamingo3x.jpg 3x,  /wp-content/uploads/flamingo2x.jpg 2x,  /wp-content/uploads/flamingo1x.jpg 1x  "  src="/wp-content/uploads/flamingo-fallback.jpg" > 

If you open the contextual menu (right-click or two-finger-tap) on the image above and open the image ina new tab, you can see which version your browser selected.

Specifying Image Width

The other way to inform the browser about the different sizes is to actually specify the image width in pixels. This has some advantages, it seems, because it gives the browser more information about the images, so it can make a better decision about which one to select. This is also good if your image versions aren’t in exact proportion to each other. (That might be the case if they were auto-resized by your Content Management System or if you downloaded them as different sizes from a site like WikiMedia Commons or Flikr.)

For image width, you use a w instead of an x.

<img  srcset="  /wp-content/uploads/flamingo4x.jpg 4025w,  /wp-content/uploads/flamingo3x.jpg 3019w,  /wp-content/uploads/flamingo2x.jpg 2013w,  /wp-content/uploads/flamingo1x.jpg 1006w  "  src="/wp-content/uploads/flamingo-fallback.jpg" > 

Speed Up Rendering with sizes

If you are using a srcset to specify width, the browser has to make some decisions about which image to download. Unfortunately, it can’t figure that out until it knows the rendered size of the image — how large it will actually appear on the screen.

You can let the browser wait to figure this out (once it has parsed all the CSS), or you can give it enough information ahead of time so that it can start loading the correct image right away. This information can be provided with the width and height attributes.

Image Density vs. Width. Which one to choose?

Based on non-scientific surveys (i.e. looking around), it seems that image density (2x, 3x, 4x) is more common. However, there are some good reasons for preferring to specify pixel width:

  • more flexible — You can create more size variations, at non-regular multiples.
  • easier — Many CMS, website builders and image-sharing sites already create or provide multiple image sizes. You can simply use them without making sure they are exactly proportionate to each other.
  • smarter — Specifying actual width in pixels provides more information to the client browser, which means it is more likely to be able to select the most appropriate image for the context.

While either way should work, it is probably the case that specifying exact image widths is the best way to go.

html.com

The term «responsive images» has come to mean «responsive images in HTML», in other words, the srcset and sizes attribute for <img> and the <picture> element. But how do the capabilities that these things provide map to CSS?

CSS generally wasn’t really involved in the responsive images journey of the last few years. That’s for good reason: CSS already has the tools. Responsive images was, in a sense, just catching up to what CSS could already do. Let’s take a look.

srcset in CSS

In HTML, srcset is like this (taken from the Picturefill site):

<img srcset="   examples/images/image-384.jpg 1x,    examples/images/image-768.jpg 2x  " alt="…">

One image for 1x displays, a larger image for 2x displays. If we wanted to do that same thing, only as a background-image in CSS, we could do:

.img {   background-image: url(examples/images/image-384.jpg);   }  @media    (-webkit-min-device-pixel-ratio: 2),    (min-resolution: 192dpi) {    .img {   background-image: url(examples/images/image-768.jpg);   }  }

There is a difference here, though. As I understand it, the way srcset is spec’d out is a bit like a suggestion. The attribute and value provide information about what is available and the browser decides what is best at the moment. Or at least, it could, if browsers chose to implement it that way. With a @media query, what is declared shall be.

Resolution media queries are fairly well supported:

Srcset html
Browser support for resolution media queries

There is another way as well, that is actually closer to how srcset works, and that’s using the image-set() function in CSS:

.img {   background-image: url(examples/images/image-384.jpg);   background-image:    -webkit-image-set(   url(examples/images/image-384.jpg) 1x,   url(examples/images/image-768.jpg) 2x,   );   background-image:    image-set(   url(examples/images/image-384.jpg) 1x,   url(examples/images/image-768.jpg) 2x,   );  }

It has a little less support than resolution queries:

Srcset html
Browser support for image-set()

It’s much closer to srcset, not only because the syntax is similar, but because it allows for the browser to have a say. According to the (still in draft) spec:

The image-set() function allows an author to ignore most of these issues, simply providing multiple resolutions of an image and letting the UA decide which is most appropriate in a given situation.

There is no perfect 1:1 replacement for srcset in CSS, but this is pretty close.

sizes in CSS

The sizes attribute in HTML is very directly related to CSS. In fact, it basically says: «This is how I intend to size this image in CSS, I’m just letting you know right now because you might need this information right this second and cannot wait for CSS to download first.»

Sample:

<img   sizes="(min-width: 40em) 80vw, 100vw"   srcset=" ... "   alt="…">

Which assumes something like this in the CSS:

img {   width: 100%;  }  @media (min-width: 40em) {   /* Probably some parent element that limits the img width */   main {   width: 80%;   }  }

But sizes alone doesn’t do anything. You pair it with srcset, which provides known widths, so the browser can make a choice. Let’s assume just a pair of images like:

<img   sizes="(min-width: 400px) 80vw, 100vw"   srcset="examples/images/small.jpg 375w,   examples/images/big.jpg 1500w"   alt="…">

The information in the markup above gives the browser what it needs to figure out the best image for it. The browser knows 1) it’s own viewport size and 2) it’s own pixel density.

Perhaps the browser viewport is 320px wide and it’s a 1x display. It now also knows it will be displaying this image at 100vw. So it has to pick between the two images provided. It does some math.

375 (size of image #1) / 320 (pixels available to show image) = 1.17
1500 (size of image #2) / 320 (pixels available to show image) = 4.69

1.17 is closer to 1 (it’s a 1x display), so the 375w image wins. It’ll try to not go under, so 1.3 would beat 0.99, as far as I understand it.

Now say it was a 2x display. That doubles the amount of pixels needed to show the images, so the math is:

375 / 640 = 0.59
1500 / 640 = 2.34

2.34 wins here, and it’ll show the 1500w image. How about a 1x display with a 1200px viewport?

375 / (80% of 1200) = 0.39
1500 / (80% of 1200) = 1.56

The 1500w image wins here.

This is kinda weird and tricky to write out in CSS. If we just think about 1x displays, we end up with logic like…

  • If the viewport is less than 375px, use the 375w image.
  • If the viewport is larger than 375px but less than 400px, use the 1500w image (because otherwise we’d be scaling up).
  • At 400px, the image moves to 80vw wide, so it’s safe to use the 375w image for a littttttle bit ( (between 400px and 468px)
  • Over 468px, use the 1500w image.

Which we could write like:

img {   background-image: url(small.jpg);  }  /* Only override this if one of the conditions for the 1500w image is met */  @media    (min-width: 375px) and (max-width: 400px),   (min-width: 468px) {   main {   background-image: url(large.jpg);   }  }

In this exact case, a 2x display, even at a really narrow width like 300px, still requires 600px make that 1.0 minimum quality, so we’d also add that to the logic:

.img {   background-image: url(small.jpg);  }  /* Only override this if one of the conditions for the 1500w image is met */  @media    (min-width: 375px) and (max-width: 400px),   (min-width: 468px),   (-webkit-min-device-pixel-ratio: 2),    (min-resolution: 192dpi) {   .img {   background-image: url(large.jpg);   }  }

The complexity of this skyrockets the more breakpoints (sizes) and the more provided images. And it’s still not a perfect match for what responsive images (in HTML) can do, since it doesn’t allow for browser discretion (e.g. the potential for a browser to consider other factors [i.e. bandwidth] to choose an image).

picture in CSS

An example:

<picture>   <source srcset="extralarge.jpg" media="(min-width: 1000px)">   <source srcset="large.jpg" media="(min-width: 800px)">   <img srcset="medium.jpg" alt="…">  </picture>

This kind of thing is a fairly straight-forward conversion to media queries. The exact media queries are right there to copy:

.img {   background-image: url(medium.jpg);  }  @media (min-width: 800px) {   .img {   background-image: url(large.jpg);   }  }  @media (min-width: 1000px) {   .img {   background-image: url(extralarge.jpg);   }  }

No surprise, this can get more complicated, because srcset can do it’s thing within the picture element as well:

<picture>   <source srcset="large.jpg, extralarge.jpg 2x" media="(min-width: 800px)">   <img srcset="small.jpg, medium.jpg 2x" alt="…">  </picture>

Which translates to:

.img {   background-image: url(small.jpg);  }  @media   (-webkit-min-device-pixel-ratio: 2),    (min-resolution: 192dpi) {   .img {   background-image: url(medium.jpg);   }  }  @media   (min-width: 800px) {   .img {   background-image: url(large.jpg);   }  }  @media   (-webkit-min-device-pixel-ratio: 2) and (min-width: 800px),    (min-resolution: 192dpi) and (min-width: 800px) {   .img {   background-image: url(extralarge.jpg);   }  }

Again, this is just waiting to blow up in complexity as you add a few more images and conditions. Slightly better with image-set():

.img {   background-image: url(small.jpg);   background-image:    -webkit-image-set(   "small.jpg" 1x,   "medium.jpg" 2x,   );   background-image:    image-set(   "small.jpg" 1x,   "medium.jpg" 2x,   );  }  @media   (min-width: 800px) {   .img {   background-image: url(large.jpg);   background-image:    -webkit-image-set(   "large.jpg" 1x,   "extralarge.jpg" 2x,   );   background-image:    image-set(   "large.jpg" 1x,   "extralarge.jpg" 2x,   );   }  }

Could mixins help?

Probably? I’d love to see a Sass @mixin that would take all these params, factor in the image sizes (that it figures out itself by hitting the disk), and spits out some quality responsive-images-in-CSS code. Maybe there is even a way to combine resolution queries and image-set() syntaxes?

Are we actually doing this?

I’m curious how many people are actively handling responsive images in CSS. Perhaps even in a middle-ground kinda way of just swapping out larger images at large breakpoints? I wonder if, because picture/srcset is often automated, that actually has a higher adoption rate than responsive images in CSS does?

css-tricks.com

The "responsive images" problem

Five years ago, Ethan Marcotte coined the term “responsive web design” and gave it three defining ingredients: fluid grids, flexible media, and media queries.

That second ingredient, “flexible media” turned out to be a bit of a bugbear.

You see, most of the media on the web is bitmap images. Heck, measured by bytes, most of the web is bitmap images. And bitmap images are fixed. They have a fixed height and a fixed width, and while it’s possible to make them visually grow and shrink using width and max-width CSS declarations, forcing users on small, low-resolution displays to load enormous images which have been sized to look good on high-resolution displays is a performance disaster. Every time we send a user more pixels than their device can use, we’re asking them to load data which they’ll end up throwing away. We’re sending them waste.

How much waste? Tim Kadlec has estimated that — for users on low-res mobile devices — 72% of image bytes served up by responsive pages are wasted. Responsive pages are sending small-screened users nearly four times as much data as they need.

New markup is here to save the day. We can’t include a single image resource that’ll work for everybody, but by using new responsive image features, we can stuff multiple resources into a single <img> and mark them up in such a way that browsers will load the most appropriate resource out of the set. We can mark up image elements which have the ability to adapt.

Let’s dive in with an example: a news-y article page with a single, large-ish image up top:

https://ericportis.com/etc/cloudinary/castro-on-the-line/

Responsification with srcset and sizes

srcset

How can we make this image responsive? The first tool in our belt is an <img> attribute named srcset. srcset allows us to stuff multiple resources into a single <img>, via a comma separated list:

We label each resource with a “width descriptor” — those numbers with 'w's after them, above. These let the browser know how wide each resource is. If a resource is 1024 pixels wide, stick a 1024w after it in srcset.

Browsers will load the resource that best matches the current context. So, if the image is 512px wide on the layout, users on standard screens will probably get medium.jpg, and users on HiDPI display will probably get large.jpg.

Why “probably?” Ultimately, browsers decide which users get which resources. And we, as authors, can’t necessarily predict which sorts of users will get what. This is a good thing! Browsers know a lot more about their context than we do. They have a wealth of information about each user’s device, connection, and preferences and the pick-as-you-please philosophy of srcset lets them leverage it.

So, let’s add a srcset attribute to an <img>:

Unfortunately, that won’t quite cut it. When browsers encounter our srcset, they’re missing a crucial piece of information: the <img>’s layout width. In order to know an image’s display dimensions, browsers have to load and parse all of its page’s CSS – something which usually happens long after srcset-parsing. To cope, we need to give the browser an estimate of the layout width of the image right in our markup, using a new attribute: sizes.

sizes

sizes takes CSS lengths. If our <img> had a fixed width, we could simply stick that width in a sizes and call it a day. For instance – if it was always 640px across on the layout, our sizes would look like this:

Our example image is a little more complicated. Below its max width of 30em, it occupies the full width of the viewport: 100vw. Above that max-width, it will always be 30em wide (learn about 'em' and 'vw' CSS units)

So our image has two possible sizes. Luckily, just like srcset, sizes lets us supply multiple values in a comma-separated list. And it lets us tell the browser which lengths to use, when, using media queries. So to give the browser a complete picture of our <img>’s dynamic layout width, we can mark it up with the following:

That says, if the viewport is at least 30em wide, this image will be 30em wide[1]. Otherwise, the image will be 100vw wide.

Putting all of the pieces together, we arrive at the following markup:

This gives us a fluid, adaptable image, which will look crisp on large, hi-res displays and minimize the number of wasted image bytes sent to users on low-res devices[2].

But! Now we, as authors, have a new problem: creating and managing three resources instead of just one.

Rendering small, medium, and large versions for our single-image example is a minor inconvenience. But when multiplied by a whole page’s worth of images, this extra work becomes a real burden. Asking poor, mistake-prone humans to render multiple versions of images at specific sizes very carefully and entirely by hand is both cruel and foolish. We need to automate.

Cloudification

Using Cloudinary, we can upload a single, canonical, high-resolution image to the cloud and deliver it in as many different sizes as we want via URL parameters (or Cloudinary’s various SDKs). Controlling our images’ technical characteristics via text and code has enormous benefits:

  • Image characteristics are easy to author, see, and alter, right from the markup
  • We can encode these characteristics directly in markup templates
  • We can track changes to these characteristics using version control

Using Cloudinary, adding a new image size (or changing an old one) on a site with thousands of images is as easy as changing a few lines in a template file. And content authors only have to worry about creating and uploading the highest-resolution image that they have; the nitty-gritty details of how that image will be variously compressed, sized, and served to users are handled automatically.

So let’s re-visit our example. And this time let’s not simply assume that we have multiple down-sized versions of our image readily at hand — let’s generate those resources with Cloudinary.

After creating a free Cloudinary account I uploaded the full-res (1.2MB!) version of the example image to my Media Library and gave it an easy-to-remember name: on_the_phone. Once uploaded, I can access it using the following URL.

Let’s break this URL down:

  • res.cloudinary.com/: the base Cloudinary URL
  • eeeps: my Cloudinary cloud name
  • image/upload/: the path to images uploaded to my media library
  • on-the-phone the name of the image we’d like to access
  • .jpg: the desired format. We could just as easily request a .png or .gif here; even though the original, uploaded image is a JPEG, Cloudinary will do the conversion on the fly.

All of the resizing action is going to happen between the upload/ and the image name. This is where image transformations go — the bits that are going to let us control exactly how our image is compressed, shaped, and sized for delivery[3].

The first thing that we’re going to want to do to this image is scale it down. To do that, we’ll use Cloudinary’s width parameter. Stick a w_ and a number into our URL, and Cloudinary will give us our image scaled to that many pixels across.

This scaled-down, 512-pixel-wide image weighs in at 86KB. How could we slim it down even further?

Cloudinary’s default compression settings are fairly conservative, resulting in heavy images of high quality. We can choose our own tradeoff – sacrificing a little quality for lighter images – using the quality parameter. The quality parameter takes a number between 0 and 100; after a little trial and error, I settled on 70.

This results in an image that’s 46KB — half the size of the unq_’d version! What else could we do to cut weight? What if tried a different format entirely, like Google’s relatively-new WebP format?

That cuts the size of the image by more than a third again, bringing it down to 36KB. But Here's what that WebP looks like in anything but Chrome:

That clearly won’t do. How can we send new, advanced image formats to browsers that support them, without showing broken image icons to browsers that don’t?

There’s a whole new markup pattern that’s been spec’d specifically to address this problem, but using Cloudinary, we don’t need it. Just stick an f_auto parameter into an image URL, and Cloudinary will perform some server-side content-negotiation magic to ensure that every browser gets the latest and greatest format that it supports:

When accessing this URL, Chrome will get a WebP, Edge and IE 9+ will get a JPEG-XR, and everybody else will get a JPEG.

Okay – now that we know how to use Cloudinary’s image transformations to generate resized (and optimized) versions of our original, let’s stick some Cloudinary URLs into our responsive image markup:

That’s the fully-responsive <img> as it appears on our example page.

This <img> will adapt right along with our responsive layout, serving a well-optimized version of our resource to users with differing viewport sizes, device resolutions, and browser-format-support capabilities.

Even better, with this markup, we bring the number of image resources that we have to worry about creating and managing back down to one: the high-res original we upload to Cloudinary. And if we ever want to tweak how we’re actually delivering that image to users, it’s as simple as changing a few characters in our HTML.

Responsive images are here, and cloud-based image hosting makes them easy.

Thus concludes part one of a two-part series. Next time, I’ll show you how to pair <picture> with Cloudinary’s cropping transforms to add another dimension of adaptability to our images: art direction. Stay tuned!


[1]: Particularly sharp readers may notice a slight problem with this: em are relative, and 30em in one context might not equal 30em in another. Within the context of sizes, an em is always equal to the default font size (usually 16px). But within the context of a CSS declaration, the size of an em is dependent on the font-size of the selected element. And indeed, our page’s viewport-sized typography means that the two 30ems will almost never be precisely the same. But you know what? They’re close enough! A precise sizes value would make our markup harder to read, understand, and maintain – and would only effect which source was chosen in a tiny number of cases. In horseshoes, hand grenades, and sizes: close counts.

[2]: How do browsers actually use srcset and sizes to pick a source? They divide the resource widths (the ws), by the current layout width (figured out via sizes) to calculate each resource’s “image density”. So, let’s say our sizes evaluates to a layout width of 512px, and we’re working with a srcset="small.jpg 256w, medium.jpg 512w, large.jpg 1024w". The image densities would work out to:

small.jpg: 256w resource width ÷ 512px layout width = 0.5x image density medium.jpg: 512w resource width ÷ 512px layout width = 1x image density large.jpg: 1024w resource width ÷ 512px layout width = 2x image density

Browsers make their decision based on these image densities. So users on 1x devices will probably get medium.jpg, users on Hi-DPI displays will most likely load large.jpg, and perhaps users on slow connections, or who’ve set some sort of preference stating that they suffer from poor eyesight will get small.jpg. But again, there’s no way for us, as authors, to know for certain which sorts of users will get what. In the browser we trust.

[3]: Cloudinary’s SDK frameworks give you language-specific tools to build these URLs indirectly. Check out the tabs in the examples to see how achieve each transformation using your framework of choice.

cloudinary.com

Часто возникает желание использовать адаптивные по ширине изображения: на десктопной версии, в анонсах постов, они маленькие; сжимаем окно браузера — анонсы расширяются, а с ними растет размер изображения.

Вот, например, сайт одной газеты, которым мы занимаемся.

1. Десктопное разрешение. Ширина изображения анонсы 322 пксл.

Маленькие анонсы

2. Сжимаем браузер. Анонсов в горизонтали становится меньше, при этом ширина изображения увеличивается до 410 пксл.

Среднее разрешение, картина уже больше

3. Если еще сжать браузер, анонс в горизонтали останется один и ширина изображения станет самой большой (656 пксл). Как видно из скриншота ниже, качество изображения с мелкими деталями станет просто ужасным (если исходное изображение — десктопное и имеет ширину 322 пксл).

Плохое качество изображения анонса

Как же быть? Можно, конечно, сделать ширину изображения анонса 656 пксл (самое широкое, которое только может быть) и вывести его для всех ширин браузера. При этом браузер будет масштабировать в сторону уменьшения данное изображение без проблем. Но мы будем загружать пользователю большое изображение даже в том случае, когда оно ему не нужно.

На помощь приходит атрибут srcset тега img. Можете почитать по нему официальную документацию (текст на столько длинный, что браузер тормозит на моем вполне резвом компе). Смысл этого атрибута в том, чтобы через запятую перечислить URL различных вариантов изображения с различной шириной, а браузер сам решит, какой из предложенных вариантов окажется на данный момент оптимальным.

Стандартный вариант

<img src="/wp-content/cache/thumb/9712274fc_322x190.jpg" width="322" height="190" alt="Описание картинки">

Добавляю srcset исходя из нашей задачи

<img src="/wp-content/cache/thumb/9712274fc_322x190.jpg" width="322" height="190" alt="Описание картинки" srcset="/wp-content/cache/thumb/9712274fc_410x241.jpg 410w, /wp-content/cache/thumb/9712274fc_656x387.jpg 656w, /wp-content/cache/thumb/9712274fc_322x190.jpg 322w">

Только srcset:

srcset="/wp-content/cache/thumb/9712274fc_410x241.jpg 410w, /wp-content/cache/thumb/9712274fc_656x387.jpg 656w, /wp-content/cache/thumb/9712274fc_322x190.jpg 322w"

Как видите, скрипт создал копии изображения для нужных мне ширин. Рядом с URL я указал ширину изображения и перечислил их через запятую.

Магия заключается в том, что качество изображения станет нормальным: браузер выберет тот вариант, который оптимален для ширина окна на данный момент. Это работает в современных браузерах и на мобильных устройствах.

Чтобы HTML-валидатор не ругался, нужно добавить еще один атрибут тегу img: sizes=»100vw». Странно, что валидатор без данного атрибута не пропускает тег img, т.к., согласно спецификации, его может и не быть.

Поскольку я работаю с WordPress (чего и вам желаю), для построения миниатюр заданного размера использую плагин Kama Thumbnail. После установки плагин позволяет пользоваться своей функцией kama_thumb_src(‘w=’ . $w . ‘&h=’ . $h), где переменные w, h передают ширину и высоту создаваемой копии изображения, которое, после создания, кешируется. Прекрасный плагин =)

Чтобы ускорить процесс заполнения атрибутов srcset, я написал небольшую функцию.

  function morkovin_get_srcset($width, $height, $array_srcset_width, $post_id, $def_src = "/images/no-photo.jpg") {   if ( function_exists('kama_thumb_src') ) {   $srcset_array = array();     $array_srcset_width[] = $width;     foreach ($array_srcset_width as $item_width) {   $item_height = $item_width * $height / $width;   if ( kama_thumb_src('w='.$item_width.'&h='.$item_height.'&post_id='.$post_id) ) {   $srcset_array[] = kama_thumb_src('w='.$item_width.'&h='.$item_height.'&post_id='.$post_id).' '.$item_width.'w';   } else {   $srcset_array[] = kama_thumb_src('w='.$item_width.'&h='.$item_height.'&src='.get_stylesheet_directory_uri().$def_src).' '.$item_width.'w';   }   }     $src_result = 'srcset="'.implode(", ", $srcset_array).'"';     return $src_result;   } else {   return false;   }  }  

Первые два аргумента функции — это ширина и высота исходной картинки (в примере это 322*190 пксл). Далее идет массив, в котором через запятую нужно передать все дополнительные ширины изображений (высоты будут вычисляться по пропорции автоматически). $post_id — это идетификатор поста, который нужен функции kama_thumb_src, чтобы найти исходное изображения для анонса. Последний аргумент — это путь к картинке по-умолчанию (отображается, если изображение не задано), отсчитывается от папки с темой.

Пример использования функции.

  $w = 322;  $h = 190;    $post_id = get_the_id();  $item_srcset = morkovin_get_srcset( $w, $h, array(410, 656), $post_id );      if (kama_thumb_src()) {  	echo '<img src="' . kama_thumb_src('w=' . $w . '&h=' . $h) . '" width="' . $w . '" height="' . $h . '" alt="' . get_the_title() . '" '.$item_srcset.' sizes="100vw"/>';  }  

www.sdelaysite.com

Синтаксис

<element srcset="[значение]">

Значения

В качестве значения данного атрибута указывается одна или более строк допустимых непустых URL-адресов, каждый из которых отделен от следующего с помощью символа «,» ЗАПЯТАЯ. Каждая строка может состоять их следующих частей:

  • URL файла с изображением;
  • дескриптор ширины, который представляет собой целое положительное число, за которым следует символ «w» (например: 600w);
  • дескриптор плотности пикселей, представляет собой положительное десятичное число, за которым следует символ «x».

Каждая строка в списке должна содержать обязательно URL-адрес альтернативного изображения и по желанию дескриптор ширины или плотности пикселей. Если никакой дескриптор не задан, то по умолчанию он равен 1x.

Если браузер не поддерживает атрибут srcset, по умолчанию файл с изображением импортируется с помощью атрибута src. Вот почему так важно включать изображение 1x, которое может отображаться на любых устройствах, независимо от их свойств. Если браузер поддерживает атрибут srcset, вы можете определять список источников изображений и условий (через запятую) до поступления запроса. В результате загружаются и выводятся на экран только те изображения, которые соответствуют параметрам устройства.

Применяется к тегам

Элементы Атрибут
<source> srcset
<img> srcset

Отличия HTML 4.01 от HTML 5

Атрибут был добавлен в HTML5.

Пример использования:

Атрибут srcset (Элемент <img>)

В приведенном выше примере атрибут sizes определяет размеры изображения с помощью различных медиазапросов. Если размер окна браузера не превышает 20em, изображение будет занимать 30% области просмотра. При размере браузера от 20em до 30em это значение увеличивается до 60%, а при размере от 20em до 30em изображение будет занимать 90% области просмотра.

Атрибут srcset (Элемент <source>)

Веб-разработчикам часто нужно использовать различные версии одного и того же изображения, чтобы эффективно предоставлять их в соответствии с широким спектром разрешений экрана и плотности пикселей, доступных на современных устройствах. Если экран маленький и изображение масштабируется вниз, то его часть может оказаться не видимой. Решить эту проблему помогает использование art direction как в примере выше.

Спецификации

Спецификация Статус
HTML 5.1 (W3C) Рекомендация

Учебник HTML

HTML уроки: HTML Атрибуты

HTML Изображения

wm-school.ru


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.

Adblock
detector