В девелоперских сборках браузеров Chrome, Firefox и Opera появилась поддержка нового элемета picture
, призванного решить ряд проблем возникающих при разработке адаптивных дизайнов. Давайте рассмотрим его подробнее.
Новый элемент picture
, решает следующие задачи, встающие перед разработчиком адаптивных веб-приложений (я воспользуюсь классификацией, предложенной pepelsbey на одной из недавних конференций по фронтенду):
- Ретина, т.е. экраны с плотностью точек на дюйм 150 и выше, на которых обычное изображение выглядит размыто
- Адаптивность, задача изменения размеров изображения согласно вашим правилам, прописанным в дизайне в зависимости от размера вьюпорта.
- Формат, возможность использовать современные форматы, такие как WebP, если они поддерживаются браузером
- Кадрирование или Художественные цели. Обрезка маловажных частей изображения, при показе на устройствах с меньшим экраном.
Сложив первые буквы, получаем мнемонику РАФК
Синтаксис
Условно, расширенный синтаксис нового элемента выглядит так
<picture>
<source
srcset="<список URL c дескрипторами>"
[sizes="<ваши размеры в зависимости от раскладки>"]
[media="<медиавыражение>"]
[type="<mime/type>"]
>
<source ...>
...
<img src="image.jpg" alt="My image"
[srcset="<список URL с дескрипторами>"]
[sizes="<ваши размеры в зависимости от раскладки>"]>
</picture>
Элемент picture
не рендерит никакой контент, а лишь является справочным контейнером для вложенного в него тега img
.
Поэтому для большинства задач хватит сокращенной записи, совсем без использования picture
<img src="image.jpg" alt="My image"
[srcset="<список URL с дескрипторами>"]
[sizes="<ваши размеры в зависимости от раскладки>"]>
Давайте рассмотрим как решаются вышеозначенные проблемы с помощью нового элемента. Все файлы примеров можно найти в этом репозитории github.com/fetis/picture
Для тестирования примеров из данной статьи на десктопе вам понадобятся либо Firefox Nighlty (поддержка picture
включается настройкой dom.image.picture.enable
в about:config), либо Chrome Canary, либо Opera Developer. На мобильном устройстве новый элемент можно протестировать в Chrome Beta
Ретина
У нас есть изображение 400х300 пкс, которое мы хотим также красиво показывать при двукратной и трехкратной плотности пикселей. Для этого готовим еще 2 картинки, размерами 800x600 и 1200х900 и пишем следующий код
<img
src="images/400.jpg"
srcset="images/800.jpg 2x, images/1200.jpg 3x"
width="400" height="300"
>
2x
и 3x
это дескрипторы плотностей пикселей, они говорят браузеру, что вот эти картинки были подготовлены для вот этой плотности, если хочешь, можешь использовать. Обратите внимание, они не заставляют бразуер использовать эти картинки, а только подсказывают ему. Окончательное решение остается за ним в зависимости от других условий, например, текущего соединения.
Атрибут src
в данном случае служит источником картинки для плотности < 2 и фолбеком на случай, если браузер не поддерживает новый элемент.
Адаптивность
Представим раскладку, в которой есть единственная контрольная точка (breakpoint) 700пкс. При размере вьюпорта более 700 пкс мы показываем справа сайдбар и размер нашего изображения должен быть 75% от ширины экрана. В противном случае сайдбар располагается в конце страницы и изображение должно быть растянуто на всю ширину. Это реализуется следующим кодом
<img
src="images/400.jpg"
srcset=" 400w, images/800.jpg 800w, images/1200.jpg 1200w"
sizes="(min-width: 700px) 75vw, 100vw"
>
400w, 800w, 1200w
— это дескрипторы ширины, они подсказывают браузеру картинка какой ширины находится по данному URL и на основе этой информации браузер принимает решение какое изображение лучше всего подойдет в текущей ситуации. Как и в случае с ретиной информация носит рекомендательный характер и окончательное решение какое изображение грузить остается за браузером.
Одновременное использование дескрипторов плотности и ширины недопустимо.
В атрибуте sizes
перечисляются размеры изображения для всех контрольных точек в нашем дизайне. Контрольные точки задаются в виде обычного медиавыражения, браузер берет первое, которое возвращает Истину и дальше цепочку не рассматривает. Для значения ширины используется новая единица длины vw, которая возвращает значение в процентах от ширины вьюпорта.
Если для картинки нет необходимости использовать контрольные точки, то запись можно сократить до такой sizes="100vw"
. А для более сложных дизайнов можно использовать CSS-функцию calc()
, например
sizes="(max-width: 30em) 100vw, (max-width: 50em) 50vw, calc(33vw - 100px)"
Самый сложный в поведении атрибут на мой взгляд. Если не указывать sizes
, то браузер всегда выбирал самую большую картинку. В сочетании с width
не работает, хотя казалось бы логичное сочетание и ряд других глюков. Возможно это особенности ранней реализации.
Как видите, мы уже покрыли 80% потребностей адаптивной верстки, а еще ни разу не использовали picture
, настало время ему тоже вступить в игру.
Формат
Использование различных форматов для изображений мало отличается от способов используемых для тегов video
или audio
<picture>
<source srcset="images/400.webp" type="image/webp">
<img src="images/400.jpg"
width="400" height="300"
>
</picture>
Мы указываем список источников и mime/type для каждого, а браузер уже выбирает первый, который знает. В качестве фолбека используется изображения из атрибута src
.
Кадрирование
Когда мы показываем фото на меньшем экране иногда имеет смысл обрезать лишние детали, оставив только основную часть. С этой задачей нам поможет справиться атрибут media
<picture>
<source media="(min-width: 900px)" srcset="images/original.jpg 1200w" sizes="100vw">
<source media="(min-width: 700px)" srcset="images/800crop.jpg 800w" sizes="100vw">
<img
srcset="images/400crop.jpg 400w"
sizes="100vw"
>
</picture>
В каждом атрибуте media
мы задаем медиавыражение, при котором у нас будет меняться исходное изображение и, в отличие от предыдущих примеров, браузер будет обязан ему следовать. Обратите также внимание как кадрирование здесь сочетается с адаптивностью, чтобы растянуть изображение на всю ширину.
РАФК
А теперь все 4 метода в одном флаконе :) Возможно так будет выглядеть вставка картинок через пару лет (пример из блога Оперы)
<picture>
<source
media="(min-width: 1280px)"
sizes="50vw"
srcset="opera-fullshot-200.webp 200w,
opera-fullshot-400.webp 400w,
opera-fullshot-800.webp 800w,
opera-fullshot-1200.webp 1200w,
opera-fullshot-1600.webp 1600w,
opera-fullshot-2000.webp 2000w"
type="image/webp">
<source
sizes="(min-width: 640px) 60vw, 100vw"
srcset="opera-closeup-200.webp 200w,
opera-closeup-400.webp 400w,
opera-closeup-800.webp 800w,
opera-closeup-1200.webp 1200w,
opera-closeup-1600.webp 1600w,
opera-closeup-2000.webp 2000w"
type="image/webp">
<source
media="(min-width: 1280px)"
sizes="50vw"
srcset="opera-fullshot-200.jpg 200w,
opera-fullshot-400.jpg 400w,
opera-fullshot-800.jpg 800w,
opera-fullshot-1200.jpg 1200w,
opera-fullshot-1600.jpg 1800w,
opera-fullshot-2000.jpg 2000w">
<img
src="opera-closeup-400.jpg" alt="The Oslo Opera House"
sizes="(min-width: 640px) 60vw, 100vw"
srcset="opera-closeup-200.jpg 200w,
400w,
opera-closeup-800.jpg 800w,
opera-closeup-1200.jpg 1200w,
opera-closeup-1600.jpg 1600w,
opera-closeup-2000.jpg 2000w">
</picture>
Здесь используются 2 формата JPEG и WebP. При ширине экрана более 1280 пкс показывается полноразмерная картинка в половину вьюпорта. При ширине от 640 до 1279 показывается обрезанное фото на 60% ширины вьюпорта. При ширине экрана меньше 640пкс показывается обрезанная фотография на 100% ширины. Выбор под текущее DPI экрана производится на основе ширины исходных файлов.
Дополнительная информация
Поддержка браузерами caniuse.com/#search=picture
Спецификация www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-picture-element
Рабочая группа и типовые задачи, которые они решали с помощью нового элемента responsiveimages.org/
Множество примеров использования dev.opera.com/articles/responsive-images/
Автор: fetis26