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

16

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

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

Дуже багато хорошого

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

Чисто теоретично, скажімо, у вас є колонка шириною 750px з зображенням у хэдере. Найшвидший і ледачий спосіб це створити зображення шириною в 1500px і відображати його на всіх екранах:

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

У поєднанні з CSS масштаб зображення завжди буде підлаштовуватися під розмір колонки:

article {
width: 750px;
margin: 0 auto;
}
article header img {
width: 100%;height: auto;
}

Зображення в два рази ширше контейнера (1500px проти 750px), однак воно масштабується, щоб повністю вмістити. Це означає, що чіткість і різкість зображення підвищаться на Retina/ HiDPI екранах з-за високої щільності пікселів.

Є тільки одна проблема: content-1/images/huge.jpg відображається на всіх екранах. Користувачі з Retina екранами отримають те ж саме зображення і ефектно відкинуть 75% інформації про пікселях, так як їх екрани просто не можуть отримати будь-яких переваг з цієї інформації. Вся ця додаткова інформація збільшує вагу і час завантаження файлу, тим самим сповільнюючи завантаження сторінки: жертва, яка приноситься заради користі тільки для користувачів з hi-end Retina екранами, а для всіх інших лише додає зайвого головного болю.

Збільшення ймовірностей

Давайте в цей раз не будемо вдаватися до ледачому способом. Замість цього ми зробимо дві версії зображення: content-1/images/huge.jpg буде дорівнювати 1х версії з шириною 750px. І будемо змінювати розмітку, щоб браузер вирішував, яке з двох зображень використовувати:

Тепер браузер буде відображати ваш сайт на стандартних дозволах екрану з картинкою в 750px (content-1/images/med.jpg), а браузери на HiDPI екранах будуть відображати велику версію зображення. Так набагато краще… але якщо у вашого сайту адаптивний дизайн, а він повинен бути, то виникає ще пара складнощів.

Труднощі адаптації

Припустимо, що наша колонка не фіксованої ширини, а тягнеться:

article {
width: 80%;
max-width: 750px;
margin: 0 auto;
}

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

body {margin: 0;}
@all media and (max-width: 750px) {
article{width: 100%;}
}

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

В певний момент content-1/images/huge.jpg стає перебором, навіть на Retina екранах: ми відображаємо зображення в 1500px на старому екрані шириною в 360px. Med.jpg більше підходить до такої області перегляду: такої кількості пікселів вистачає, щоб добре відобразити зображення на менших HiDPI екранах, уникаючи виходить за всі межі розміру файлу content-1/images/huge.jpg.

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

На жаль, немає чіткої межі, коли можна використовувати «2Х» позначення: на Retina пристроях браузер зобов’язаний використовувати 2х зображення, якщо таке є, і не важливо, що це може уповільнити продуктивність.

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

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

Адаптивні підказки для зображень: з допомогою 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, про нього і піде мова в наступній статті.