От автора: начать данную статью я должен с признания: очень долгое время я не мог никак понять, как работают w дескриптор в адаптивных HTML5 изображениях, а также работу атрибута sizes. Принцип использования тега picture и изменение разрешения картинки с помощью srcset и x дескриптора были ясны, но когда все это стало намного сложнее, с приходом запятой-разделителя в синтаксис, а также появление атрибута sizes и w все стало очень запутанно. Статьи на эту тему и спецификации только усугубляли все: для чего это было все создано, и почему я хочу их применять?
После долгих размышлений над этими проблемами, а также после нескольких конференций, в которых я принял участие, я начал осмысливать, почему w и sizes так важны, и как их можно использовать… и этим пониманием я надеюсь поделиться с вами в этой и последующих статьях.
Слишком много хорошего
Начнем с допущения: вы хотите отобразить наилучшее оптимизированное bitmap изображение с самым высоким разрешением доступное для экрана, на котором будет отображаться ваш сайт.
Чисто теоретически, скажем, у вас есть колонка <article> шириной 750px с изображением в хэдере. Самый быстрый и ленивый способ это создать изображение шириной в 1500px и отображать его на всех экранах:
1 2 3 4 |
<article> <header> <img src="huge.jpg" alt> </header> |
В сочетании с CSS масштаб изображения всегда будет подстраиваться под размер колонки:
1 2 3 4 5 6 7 |
article { width: 750px; margin: 0 auto; } article header img { width: 100%;height: auto; } |
Изображение в два раза шире контейнера (1500px против 750px), однако оно масштабируется, чтобы полностью в нем поместиться. Это значит, что четкость и резкость изображения повысятся на Retina/ HiDPI экранах из-за высокой плотности пикселей.
Есть только одна проблема: huge.jpg отображается на всех экранах. Пользователи с Retina экранами получат то же самое изображение и эффектно отбросят 75% информации о пикселях, так как их экраны просто не могут получить каких-либо преимуществ из этой информации. Вся эта дополнительная информация увеличивает вес и время загрузки файла, тем самым замедляя загрузку страницы: жертва, которая приносится ради пользы только для пользователей с hi-end Retina экранами, а для всех остальных только добавляет лишней головной боли.
Увеличение вероятностей
Давайте в этот раз не будем прибегать к ленивому способу. Вместо этого мы сделаем две версии изображения: huge.jpg будет равняться 1х версии с шириной в 750px. И будем изменять разметку, чтобы браузер решал, какое из двух изображений использовать:
1 2 3 |
<header> <imgsrc="med.jpg" srcset="huge.jpg 2x" alt> </header> |
Теперь браузер будет отображать ваш сайт на стандартных разрешениях экрана с картинкой в 750px (med.jpg), а браузеры на HiDPI экранах будут отображать большую версию изображения. Так намного лучше… но если у вашего сайта адаптивный дизайн, а он должен быть, то возникает еще пара сложностей.
Сложности адаптации
Предположим, что наша колонка <article> не фиксированной ширины, а тянущаяся:
1 2 3 4 5 |
article { width: 80%; max-width: 750px; margin: 0 auto; } |
Этот код CSS и медиа запросы растянут тег article на всю ширину в браузере на маленьких экранах:
1 2 3 4 |
body {margin: 0;} @media all and (max-width: 750px) { article{width: 100%;} } |
Страница все еще нормально работает, оба изображения вмещаются в блок-контейнер благодаря раньше объявленному img в CSS выше – однако у нас появилась интересная проблема при сужении окна браузера:
В определенный момент huge.jpg становится перебором, даже на Retina экранах: мы отображаем изображение в 1500px на старом экране шириной в 360px. Med.jpg больше подходит к такой области просмотра: такого количества пикселей хватает, чтобы хорошо отобразить изображение на меньших HiDPI экранах, избегая выходящего за все границы размера файла huge.jpg.
К сожалению, нет четкой грани, когда можно использовать «2Х» обозначение: на Retina устройствах браузер обязан использовать 2х изображение, если такое доступно, и не важно, что это может замедлить производительность.
Подсказка для изображения
Большая проблема в том, что браузер не знает истинную ширину изображения, пока не загрузит его. Вот тут нам и поможет w дескриптор: с его помощью можно намекнуть браузеру о размере изображения. Примерно так:
1 |
<img src="med.jpg" srcset="med.jpg 750w, huge.jpg 1500w" alt> |
Есть три замечания:
Нельзя использовать 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.