Адаптивные подсказки для изображений: с помощью w дескриптора

Адаптивные подсказки для изображений: с помощью w дескриптора

От автора: начать данную статью я должен с признания: очень долгое время я не мог никак понять, как работают w дескриптор в адаптивных HTML5 изображениях, а также работу атрибута sizes. Принцип использования тега picture и изменение разрешения картинки с помощью srcset и x дескриптора были ясны, но когда все это стало намного сложнее, с приходом запятой-разделителя в синтаксис, а также появление атрибута sizes и w все стало очень запутанно. Статьи на эту тему и спецификации только усугубляли все: для чего это было все создано, и почему я хочу их применять?

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

Слишком много хорошего

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

Чисто теоретически, скажем, у вас есть колонка <article> шириной 750px с изображением в хэдере. Самый быстрый и ленивый способ это создать изображение шириной в 1500px и отображать его на всех экранах:

В сочетании с CSS масштаб изображения всегда будет подстраиваться под размер колонки:

Изображение в два раза шире контейнера (1500px против 750px), однако оно масштабируется, чтобы полностью в нем поместиться. Это значит, что четкость и резкость изображения повысятся на Retina/ HiDPI экранах из-за высокой плотности пикселей.

Есть только одна проблема: huge.jpg отображается на всех экранах. Пользователи с Retina экранами получат то же самое изображение и эффектно отбросят 75% информации о пикселях, так как их экраны просто не могут получить каких-либо преимуществ из этой информации. Вся эта дополнительная информация увеличивает вес и время загрузки файла, тем самым замедляя загрузку страницы: жертва, которая приносится ради пользы только для пользователей с hi-end Retina экранами, а для всех остальных только добавляет лишней головной боли.

Увеличение вероятностей

Давайте в этот раз не будем прибегать к ленивому способу. Вместо этого мы сделаем две версии изображения: huge.jpg будет равняться 1х версии с шириной в 750px. И будем изменять разметку, чтобы браузер решал, какое из двух изображений использовать:

Теперь браузер будет отображать ваш сайт на стандартных разрешениях экрана с картинкой в 750px (med.jpg), а браузеры на HiDPI экранах будут отображать большую версию изображения. Так намного лучше… но если у вашего сайта адаптивный дизайн, а он должен быть, то возникает еще пара сложностей.

Сложности адаптации

Предположим, что наша колонка <article> не фиксированной ширины, а тянущаяся:

Этот код CSS и медиа запросы растянут тег article на всю ширину в браузере на маленьких экранах:

Страница все еще нормально работает, оба изображения вмещаются в блок-контейнер благодаря раньше объявленному img в CSS выше – однако у нас появилась интересная проблема при сужении окна браузера:

В определенный момент huge.jpg становится перебором, даже на Retina экранах: мы отображаем изображение в 1500px на старом экране шириной в 360px. Med.jpg больше подходит к такой области просмотра: такого количества пикселей хватает, чтобы хорошо отобразить изображение на меньших HiDPI экранах, избегая выходящего за все границы размера файла huge.jpg.

К сожалению, нет четкой грани, когда можно использовать «2Х» обозначение: на Retina устройствах браузер обязан использовать 2х изображение, если такое доступно, и не важно, что это может замедлить производительность.

Подсказка для изображения

Большая проблема в том, что браузер не знает истинную ширину изображения, пока не загрузит его. Вот тут нам и поможет w дескриптор: с его помощью можно намекнуть браузеру о размере изображения. Примерно так:

Есть три замечания:

Нельзя использовать w и x дескрипторы вместе: придется выбрать что-то одно.

Несмотря на кажущуюся избыточность, изображения по умолчанию должны содержать атрибут srcset с w дескриптором для повышения эффективности.

W и x нельзя использовать напрямую в src: они применимы только в атрибуте srcset.

Разработка связей

W дескриптор предоставляет фактическую ширину изображения в пикселях, тем самым позволяя браузеру определить, какое изображения больше подходит в разных ситуациях. Если вы откроете эту страницу в Chrome на Retina экране и сузите ее, к примеру, вы увидите, что изображение в шапке статьи переключилось на 2х версию. Если вы будете растягивать окно браузера, то изображение вернется к 1х версии.

Глупости в браузерах

Конечно, жизнь разработчика не была бы такой радужной без различий в реализации w дескриптора в разных браузерах:

Chrome не загрузит 1х версию изображения на Retina, если доступна 2х версия. И в этом есть смысл – Chrome как бы говорит нам «Мне уже достаточно этого количества пикселей для отображения, спасибо». Однако поведение браузера может быть слегка непонятным при уменьшении окна до максимума, если в этот момент перезагрузить страницу, то совершенно ничего не изменится. Есть только одни способ заставить Chrome загружать 1х версию изображения (предположим, что страница была открыта на большом Retina экране):

Уменьшить размер экрана до необходимого.

Открыть настройки Chrome.

Очистить кэш (можно вбить в поле поиска «кэш» в правом верхнем углу).

Переключиться на вкладку со страницей и перезагрузить ее.

Firefox не загрузит 2х версию изображения динамически при уменьшении экрана и последующем увеличении. Прямо как Chrome только наоборот, браузер будет использовать 2х версию изображения. Тем не менее, при обновлении страницы загрузится необходимая версия изображения для любого размера.

Safari 8 (мобильный и настольный) не поддерживают w дескриптор, однако Safari 9 поддерживает, как и Android 4.0.

И печально, что ни IE, ни Edge все еще не поддерживают w дескриптор. Для этих браузеров можно использовать polyfill-библиотеку pictureFill.

Как я могу сообщить браузеру, какое изображение использовать?

Если вы не используете водяные знаки, как на изображении в нашей статье, будет достаточно сложно определить правильность работы srcset и w: в конце концов, в синтаксисе мы прописываем то же самое изображение, но с другим разрешением (если вам необходимо переключаться между разными изображениями, то попробуйте тег picture). А если вы на глаз не можете отличить качество изображений, как вы можете быть уверены в том, что это работает?

С помощью Chrome возможно легче всего определить работу srcset и w. Сначала, взгляните еще раз на главу «Глупости в браузерах» и уменьшите окно браузера до минимального. Затем:

Откройте панель разработчика (F12)

Перейдите на вкладку «сеть»

Обновите страницу. Вы должны увидеть, что 1х изображение загрузилось в панели «сеть».

Медленно расширяйте окно браузера. В какой-то момент вы заметите подгрузку в панель сети 2х версии изображения и автоматическую его замену с 1х версией в окне браузера.

Когда какое изображение использовать

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

Для иконок – предполагая, что SVG нельзя использовать – применяйте x дескриптор.

Для заголовков/ изображений в заголовках: используйте w в сочетании с sizes.

Для всего остального (маленькие иллюстрации, диаграммы и т.д.) загружайте обычные изображения; если можно, используйте SVG.

Заключение

Еще одни пример, как понять разницу между x и w дескрипторами, это то, что x дескриптор повышает качество изображения без оглядки на тип устройства. А w пытается находить баланс и применять оптимальное качество изображений в зависимости от производительности.

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

Источник: //thenewcode.com/

Редакция: Команда webformyself.

Метки:

Похожие статьи:

Комментарии Вконтакте: