Перейти к содержанию

Прескриптивные синтаксисы

Узнайте об элементе <picture>.

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

1
2
3
4
5
<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, который соответствует размеру области просмотра пользователя:

1
2
3
4
5
6
7
<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 первым следует поместить самый маленький источник.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<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 для оптимизации источников художественных изображений.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<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>.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<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. Например, выбор источника изображения, более подходящего для цветовой схемы, продиктованной предпочтениями пользователя:

1
2
3
4
5
6
7
<picture>
    <source
        media="(prefers-color-scheme: dark)"
        srcset="hero-dark.jpg"
    />
    <img srcset="hero-light.jpg" />
</picture>

Атрибут type

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

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

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

1
2
3
4
5
6
<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 указывается Media Type (ранее MIME type) источника изображения, указанного в атрибуте srcset каждого <source>. Это дает браузеру всю необходимую информацию для немедленного определения возможности декодирования изображения-кандидата, предоставленного этим source, без выполнения каких-либо внешних запросов - если тип медиа не распознан, то <source> и все его кандидаты игнорируются, и браузер идет дальше.

1
2
3
4
<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" не запрашиваются до тех пор, пока не будет известен макет страницы, что позволяет отложить запросы к изображениям, находящимся за пределами начальной области просмотра пользователя, до более поздних этапов рендеринга страницы, что позволяет избежать ненужных запросов. Поскольку браузер полностью понимает макет страницы в момент выполнения таких запросов, в качестве дополнения к спецификации HTML было предложено использовать атрибут sizes="auto", чтобы избежать необходимости вручную прописывать атрибуты sizes в таких случаях.

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

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

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

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

Источник — Prescriptive syntaxes

Комментарии