Теперь WebKit поддерживает srcset, и это здорово!

WebKit попал, так сказать, на первые полосы газет: наконец-то он поддерживает атрибут srcset. Как глава общественной группы W3C по отзывчивым изображениям, я уже в течение ощутимого времени попеременно то с надеждой, то с ужасом ждал этого момента. Но получается, что новости оказались хорошими для всех участников процесса — и в первую очередь для пользователей.

Как и со всем, что касается темы отзывчивых изображений, здесь все сложно — и ещё более сложно выделять из информационного шума что-либо ценное. Вот то, что вам нужно знать.

Что этот атрибут делает?

Как изначально предлагала спецификация, атрибут srcset должен позволять разработчикам определять список источников для изображения, которые будут выбраны, исходя из плотности пикселей на дисплее пользователя:

<img src="low-res.jpg" srcset="high-res.jpg 2x">

Ничего страшного в такой разметке нет. Переводим на человеческий язык:

«Используем low-res.jpg в качестве источника этого изображения на дисплеях с низким разрешениями и в тех браузерах, которые не поддерживают атрибут srcset. Используем high-res.jpg в качестве источника этого изображения на дисплеях высокого разрешения в браузерах, которые понимают атрибут srcset».

Некоторое время назад ситуация стала пугающей. Из-за значительного количества пользователей, использующих устройства с дисплеями высокого разрешения, средний сайт содержит почти мегабайт изображений. Теперь разработчики могут отдавать пользователям с дисплеями высокого разрешения соответствующие изображения. В то же время, пользователи устройств с экранами низкого разрешения не будут тратить трафик и время на загрузку этих изображений, не наблюдая при этом никакой разницы в качестве.

А разве мы не можем делать это с помощью JavaScript?

На поверхности srcset не делает ничего совсем уж особенного — он выбирает подходящий источник из атрибута и подменяет содержимое атрибута src в элементе img. Такую функцию — заменять значение атрибута — мы используем в JavaScript очень давно — по крайней мере, с 90-х. Что же нам дает эта реализация?

Мы попробовали этот подход с JavaScript на сайте BostonGlobe.com, который одним из первых решился применить у себя какой-нибудь вариант техники «отзывчивых изображений». Однако из-за предзагрузки внутри нескольких крупных браузеров (которая становится со временем все более и более агрессивной), src изображения загружается задолго до того, как у нас есть малейшая возможность применить кастомные скрипты: приходится делать два запроса на каждую картинку, которую мы показываем на экране — что лишает смысла все предприятие. Я уже описывал кое-что из того, что мы тогда делали, так что сейчас избавлю вас от нелицеприятных деталей.

А мы не можем использовать CSS?

И да, и нет. Это можно делать довольно просто с фоновыми изображениями: для этого нужно использовать сочетания медиазапросов, отвечающих за плотность пикселей. srcset в WebKit очень похож на функцию image-set, которую они же недавно включили в CSS. image-set позволяет вам определить список источников для фоновых изображений и разрешений, а потом дать браузеру принять решение, которую из них лучше всего выбрать — все это вполне вам знакомо. Единственное — до сих пор у нас не было ничего подобного для изображений, которые относятся к содержимому, а не только к презентационной части.

Использовать CSS для управлением изображениями, относящимися к содержимому — по определению плохая идея, так как мы смешиваем данные и представление. Такой подход вполне может работать в рамках маленькой демо-странички, но на большом сайте ситуация начнет очень быстро выходить из-под контроля. С точки зрения разработчика будет очень невесело заставлять CMS генерировать жуткое количество таблиц стилей с фоновыми изображениями. Еще хуже, что браузеры будут запрашивать и дополнительные таблицы стилей и изображения, которые — только если не делать это очень, очень аккуратно — пользователям совершенно не нужны. Ну и кроме того, наши изображения становятся таким образом недоступными для технологий, помогающих пользователям с ограниченными возможностями.

Самое близкое к полноценному решению на CSS – это подход, который меняет источник изображения в зависимости от значений в атрибутах data-, для этого есть хитрая CSS-техника; к сожалению, это решение во многом только теоретическое и может навсегда остаться на бумаге. Однако и это решение не позволяет избежать двойного скачивания изображений с высоким и низким разрешением — то, с чем мы столкнулись, используя JavaScript-решения. Даже если бы мы смогли применять технику Николаса в реальных условиях, у нас была бы та же проблема, что и с решениями на JavaScript — как разобраться с ненужным, лишним http-запросом?

А пропускная способность сети?

Вне зависимости от плотности дисплея, есть ряд ситуаций, в которых предпочтительнее показывать пользователю изображения с низким разрешением: например, Retina MacBook Pro, который подключен к интернету через 3G или через нестабильное Wi-Fi-соединение на конференции — и с той, и с другой ситуацией мы сталкивается постоянно.

srcset не только дает нам возможность коротко писать медиазапросы в зависимости от разрешения, но неким образом учитывает и пропускную способность сети. Конечно, это все погребено в жутком жаргоне спецификаций, но одна из самых интересных сторон srcset — то, что этот атрибут определяется как набор рекомендаций браузеру. Браузер после этого может использовать эвристику на основании того, что ему известно о контексте, или пользовательские настройки — и решить, что ему стоит скачать изображение с низким разрешением даже для retina- дисплея: представьте себе настройку в мобильном браузере, которая позволяет скачивать изображения высокого разрешения только тогда, когда вы подключены к Wi-Fi, или настройка, которая позволяет вам запрашивать только изображения низкого разрешения при нестабильном соединении.

Responsive Images

В идеале, мы хотели бы, чтобы каждое устройство получало только картинки, которые соответствуют разрешению экрана устройства. Цель здесь в том, чтобы не нагружать соединение и позволять изображениям загружаться быстрее на соответствующем дисплее. Вот типовой сценарий использования отзывчивых изображений.

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

А что это означает для элемента picture?

А вот здесь все становится совсем интересно.

Та версия srcset, которая сейчас поддерживается WebKit, соответствует первоначально предложенной спецификации srcset и той версии, над которой работает общественная группа по отзывчивым изображениям. Нам представляется, что это воплощение srcset — это краткий синтаксис для большого количества медиазапросов, связанных с разрешением, с одним ключевым отличием: браузер может менять источник изображения в зависимости от пользовательских настроек.

Хотя эта реализация соответствуют изначально предложенной спецификации srcset, текущая спецификация пытается расширить синтаксис, чтобы работать в ряде сценариев, которые призван решить элемент picture — причем спецификация использует для этого микросинтаксис, который выполняет некоторые — но далеко не все! — функции медиазапросов.

<img src="fallback.jpg" srcset="small.jpg 640w 1x, small-hd.jpg 640w 2x, large.jpg 1x, large-hd.jpg 2x" alt="…">

По нашему мнению, эта система разметки далеко не идеальна. Получается, что мы можем пользоваться только эквивалентом медиазапроса max-width, пикселями, жутким микросинтаксисом — и все это для того, чтобы повторить функциональность медиазапросов. К счастью, ни веб-разработчики, ни производители браузеров не в восторге от этого синтаксиса — и, будем надеяться, он никогда не будет реализован.

Для того, чтобы справиться с этими сценариями, существует элемент picture, который может похвастаться более гибким и более понятным синтаксисом. picture использует атрибуты media на элементах source (так же, как внутри video). Это позволяет нам выбирать источники изображений в зависимости от целого набора факторов: ширина/высота окна браузера, в px или em, — и можно использовать значения min и max — точно так же, как медиазапросы в CSS.

<picture>
    <source src="med.jpg" media="(min-width: 40em)" />
    <source src="sm.jpg" />
    <img src="fallback.jpg" alt="" />
</picture>

Спецификация picture была написана с учетом этого редуцированного синтаксиса srcset, так что его можно использовать на элементах source внутри picture точно так же, как и на элементах img.

<picture>
    <source srcset="med.jpg 1x, med-hd.jpg 2x" media="(min-width: 40em)" />
    <source srcset="sm.jpg 1x, sm-hd.jpg 2x" />
    <img src="fallback.jpg" alt="" />
</picture>

Вместе две системы разметки дают нам невероятную гибкость относительно того, какие источники изображений мы отдаем пользователям в зависимости от контекста, в котором они просматривают страницу.

Так что это действительно хорошие новости.

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

Будем надеяться, что другие браузеры пойдут по стопам WebKit, станут поддерживать эту функцию в том формате, в котором она была изначально предложена. Чтобы оставаться в курсе событий, заглядывайте на домашнюю страницу общественной группы по отзывчивым изображениям и в наш аккаунт Twitter.

Я уже писал о проблемах с отзывчивыми изображениями и теми решениями, к которым мы пришли, когда работали над сайтом Boston Globe, в моей книге, которая выйдет в серии Smashing Book, в главе «Проблемы и решения в отзывчивом веб- дизайне». Почитайте ее, она вас не разочарует.