Предписывающий синтаксис

Элемент <picture> ничего не отображает сам по себе, а вместо этого действует как механизм принятия решений для внутреннего элемента <img> , сообщая ему, что отображать. <picture> следует прецеденту, уже установленному элементами <audio> и <video> : элемент-оболочка, который содержит отдельные элементы <source> .

<picture>
   <source …>
   <source …>
    <img …>
</picture …>

Этот внутренний <img> также предоставляет вам надежный запасной шаблон для старых браузеров без поддержки адаптивных изображений: если элемент <picture> не распознается браузером пользователя, он игнорируется. Элементы <source> также отбрасываются, поскольку браузер либо вообще их не распознает, либо не будет иметь для них значимого контекста без родительского элемента <video> или <audio> . Однако внутренний элемент <img> распознается любым браузером, и источник, указанный в его src , будет отображаться как ожидалось.

«Арт-режиссерские» изображения с <picture>

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

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

Но при уменьшении размера для небольших окон просмотра центральный фокус изображения может быть потерян:

Уменьшенное изображение цветка барвинка в ширине заголовка. Пчелу едва видно.

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

Увеличенный урожай цветка барвинка.

Такого рода «обрезка» может быть достигнута с помощью CSS, но в результате пользователь запрашивает все данные, составляющие это изображение, даже если он никогда не увидит его.

Каждый source элемент имеет атрибуты, определяющие условия выбора этого source : media , который принимает медиа-запрос, и type , который принимает тип мультимедиа (ранее известный как «тип MIME»). Выбирается первый <source> в порядке источников, соответствующий текущему контексту просмотра пользователя, и содержимое атрибута srcset этого source будет использоваться для определения подходящих кандидатов для этого контекста. В этом примере будет выбран первый source с media атрибутом, соответствующим размеру области просмотра пользователя:

<picture>
  <source media="(min-width: 1200px)" srcset="wide-crop.jpg">
  <img src="close-crop.jpg" alt="…">
</picture>

Внутреннее img всегда следует указывать последним в порядке — если ни один из source элементов не соответствует критериям media или type , изображение будет действовать как источник «по умолчанию». Если вы используете медиа-запросы min-width , вам нужно сначала получить самые большие источники, как показано в предыдущем коде. При использовании медиа-запросов max-width сначала следует указывать наименьший источник.

<picture>
   <source media="(max-width: 400px)" srcset="mid-bp.jpg">
   <source media="(max-width: 800px)" srcset="high-bp.jpg">
   <img src="highest-bp.jpg" alt="…">
</picture>

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

<picture>
   <source media="(min-width: 800px)" srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w">
   <source srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w">
   <img src="fallback.jpg" alt="…" sizes="calc(100vw - 2em)">
</picture>

Конечно, изображение с пропорциями, которые могут меняться в зависимости от выбранного элемента <source> вызывает проблемы с производительностью: <img> поддерживает только один атрибут width и height , но отсутствие этих атрибутов может привести к значительному ухудшению пользовательского опыта . Чтобы учесть это, относительно недавнее , но хорошо поддерживаемое дополнение к спецификации HTML позволяет использовать атрибуты height и width в элементах <source> . Они работают для уменьшения сдвигов макета так же, как и для <img> , при этом в вашем макете зарезервировано соответствующее пространство для любого выбранного элемента <source> .

<picture>
   <source
      media="(min-width: 800px)"
      srcset="high-bp-1600.jpg 1600w, high-bp-1000.jpg 1000w"
      width="1600"
      height="800">
   <img src="fallback.jpg"
      srcset="lower-bp-1200.jpg 1200w, lower-bp-800.jpg 800w"
      sizes="calc(100vw - 2em)"
      width="1200"
      height="750"
      alt="…">
</picture>

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

<picture>
   <source media="(prefers-color-scheme: dark)" srcset="hero-dark.jpg">
   <img srcset="hero-light.jpg">
</picture>

Атрибут type

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

Как вы узнали в разделе «Форматы изображений и сжатие» , кодировка, которую браузер не может проанализировать, даже не будет распознаваться как данные изображения.

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

   <img src="image.webp"
    data-fallback="image.jpg"
    onerror="this.src=this.getAttribute('data-fallback'); this.onerror=null;"
    alt="...">

При использовании этого шаблона запрос image.webp по-прежнему будет выполняться в каждом браузере, что означает напрасную передачу для браузеров без поддержки WebP. Браузеры, которые не смогли затем проанализировать кодировку WebP, выдадут событие onerror и заменят data-fallback в src . Это было расточительное решение, но, опять же, подобные подходы были единственным вариантом, доступным во внешнем интерфейсе. Помните, что браузер начинает запрашивать изображения до того, как какой-либо пользовательский сценарий сможет быть запущен или даже проанализирован, поэтому мы не можем упредить этот процесс.

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

В атрибуте type вы указываете тип носителя (ранее MIME-тип) источника изображения, указанный в атрибуте srcset каждого <source> . Это предоставляет браузеру всю информацию, необходимую для немедленного определения, может ли изображение-кандидат, предоставленное этим source , быть декодировано без каких-либо внешних запросов — если тип носителя не распознается, <source> и все его кандидаты игнорируются. и браузер движется дальше.

<picture>
 <source type="image/webp" srcset="pic.webp">
 <img src="pic.jpg" alt="...">
</picture>

Здесь любой браузер, поддерживающий кодировку WebP, распознает тип носителя image/webp , указанный в атрибуте type элемента <source> , выбирает этот <source> и — поскольку мы предоставили только один кандидат в srcset проинструктирует внутренний <img> для запроса, передачи и рендеринга pic.webp . Любой браузер без поддержки WebP будет игнорировать source , и при отсутствии каких-либо инструкций об обратном <img> будет отображать содержимое src , как это делалось с 1992 года. Вам не нужно указывать второй элемент <source> с помощью Здесь, конечно, type="image/jpeg" — можно предположить универсальную поддержку JPEG.

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

Будущее адаптивных изображений

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

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

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

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

Хотя синтаксис контейнерных запросов только что стабилизировался (а поддержка браузеров на момент написания статьи была очень ограничена ), добавление технологий браузера, которые позволяют это сделать, предоставит элементу <picture> средство делать то же самое: потенциальную возможность Атрибут container , который позволяет использовать критерии выбора <source> на основе пространства, которое занимает <picture> элемента <img> , а не на основе размера области просмотра.

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

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