Picture — элемент, которого нет

В девелоперских сборках Chrome, Firefox и Opera появилась поддержка элемета picture, призванного решить ряд проблем возникающих при разработке адаптивных дизайнов. Давайте рассмотрим его подробнее.

Новый элемент picture, решает следующие задачи, встающие перед разработчиком адаптивных веб-приложений (я воспользуюсь классификацией, предложенной хаброюзером pepelsbey на одной из недавних конференций по фронтенду):
1. Ретина, т.е. экраны с плотностью точек на дюйм 150 и выше, на которых обычное изображение выглядит размыто
2. Адаптивность, задача изменения размеров изображения согласно вашим правилам, прописанным в дизайне в зависимости от размера вьюпорта.
3. Формат, возможность использовать современные форматы, такие как WebP, если они поддерживаются браузером
4. Кадрирование. Обрезка маловажных частей изображения, при показе на устройствах с меньшим экраном.

Сложив первые буквы, получаем мнемонику РАФК.

Синтаксис

Выглядит примерно так:

 

[html]
<picture>
<source
srcset="<список URL c дескрипторами>"
[sizes="<ваши размеры в зависимости от раскладки>"]
[media="<медиавыражение>"]
[type="<mime/type>"]
>
<source …>

<img src="image.jpg" alt="My image"
[srcset="<список URL с дескрипторами>"]
[sizes="<ваши размеры в зависимости от раскладки>"]>
</picture>
[/html]

Элемент picture не рендерит никакой контент, а лишь является справочным контейнером для вложенного в него тега img.

Поэтому для большинства задач хватит сокращенной записи, совсем без использования picture. И да, ИМДЖ НАШЭ ВСЕ.

[html]
<img src="image.jpg" alt="My image"
[srcset="<список URL с дескрипторами>"]
[sizes="<ваши размеры в зависимости от раскладки>"]>
[/html]

Давайте рассмотрим как решаются вышеозначенные проблемы с помощью нового элемента.

Для тестирования примеров из данной статьи на десктопе вам понадобятся либо Firefox Nighlty (поддержка picture включается настройкой dom.image.picture.enable в about:config), либо Chrome Canary, либо Opera Developer. На мобильном устройстве новый элемент можно протестировать в Chrome Beta.

Ретина

У нас есть изображение 400х300 пкс, которое мы хотим также красиво показывать при двукратной и трехкратной плотности пикселей. Для этого готовим еще 2 картинки, размерами 800×600 и 1200х900 и пишем код

[html]
<img
src="images/400.jpg"
srcset="images/800.jpg 2x, images/1200.jpg 3x"
width="400" height="300"
>
[/html]

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

Атрибут src в данном случае служит источником картинки для плотности < 2 и фоллбеком на случай, если браузер не поддерживает новый элемент.

Адаптивность

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

[html]
<img
src="images/400.jpg"
srcset=" 400w, images/800.jpg 800w, images/1200.jpg 1200w"
sizes="(min-width: 700px) 75vw, 100vw"
>
[/html]

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

[html]
<picture>
<source srcset="images/400.webp" type="image/webp">
<img src="images/400.jpg"
width="400" height="300"
>
</picture>
[/html]

Мы указываем список источников и mime/type для каждого, а браузер уже выбирает первый, который знает. В качестве фоллбека используется изображения из атрибута src.

Кадрирование

Когда мы показываем фото на меньшем экране иногда имеет смысл обрезать лишние детали, оставив только основную часть. С этой задачей нам поможет атрибут media

[html]
<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>
[/html]

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

РАФК

Возможно так будет выглядеть вставка картинок через пару лет (пример из блога Оперы).

[html]
<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>
[/html]

Здесь используются 2 формата JPEG и WebP. При ширине экрана более 1280 пкс показывается полноразмерная картинка в половину вьюпорта. При ширине от 640 до 1279 показывается обрезанное фото на 60% ширины вьюпорта. При ширине экрана меньше 640пкс показывается обрезанная фотография на 100% ширины. Выбор под текущее DPI экрана производится на основе ширины исходных файлов.

 

Вот и все, я думаю. Есть чем дополнить? Пишите в комменты.

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

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