- PVSM.RU - https://www.pvsm.ru -

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

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

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

Новый элемент picture, решает следующие задачи, встающие перед разработчиком адаптивных веб-приложений (я воспользуюсь классификацией, предложенной pepelsbey [1] на одной из недавних конференций по фронтенду):

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

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

Синтаксис

Условно, расширенный синтаксис нового элемента выглядит так

<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 [2]

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

Ретина

У нас есть изображение 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 [7], которая возвращает значение в процентах от ширины вьюпорта.

Если для картинки нет необходимости использовать контрольные точки, то запись можно сократить до такой 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 [8]
Спецификация www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-picture-element [9]
Рабочая группа и типовые задачи, которые они решали с помощью нового элемента responsiveimages.org/ [10]
Множество примеров использования dev.opera.com/articles/responsive-images/ [11]

Автор: fetis26

Источник [12]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/html/70581

Ссылки в тексте:

[1] pepelsbey: http://habrahabr.ru/users/pepelsbey/

[2] github.com/fetis/picture: https://github.com/fetis/picture

[3] Firefox Nighlty: http://nightly.mozilla.org/

[4] Chrome Canary: http://www.google.com/chrome/browser/canary.html

[5] Opera Developer: http://www.opera.com/developer

[6] Chrome Beta: https://play.google.com/store/apps/details?id=com.chrome.beta

[7] единица длины vw: http://dev.w3.org/csswg/css-values/#viewport-relative-lengths

[8] caniuse.com/#search=picture: http://caniuse.com/#search=picture

[9] www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-picture-element: http://www.w3.org/html/wg/drafts/html/master/embedded-content.html#the-picture-element

[10] responsiveimages.org/: http://responsiveimages.org/

[11] dev.opera.com/articles/responsive-images/: https://dev.opera.com/articles/responsive-images/

[12] Источник: http://habrahabr.ru/post/237991/