Техніка Clown Car: зображення в адаптивному вебдизайне

14

Від автора: Зараз зображення – «гаряча» тема спорів в адаптивному вебдизайне. Чому? Тому, що ще нікому не сподобалися існуючі рішення. Для полегшення нашої сильної головного болю – забезпечити користувача одним зображенням, оптимізованим до розміру і дозволу його дисплея, без втрати часу, пам’яті та пропускної здатності і на стороні клієнта – обговорюються нові елементи і атрибути.

У нас є зображення переднього плану і тла. У нас є великі і маленькі екрани. У нас – звичайні дисплеї і дисплеї з високою роздільною здатністю. У нас – сполуки з високою і низькою пропускною здатністю. У нас є книжкова й альбомна орієнтація.

Деякі даремно витрачають пропускну здатність (і пам’ять), посилаючи зображення у високому дозволі на всі пристрої. Інші усюди розсилають звичайне дозвіл, при цьому зображення виглядають непевний на високоякісних екранах. Насправді дуже хочеться відшукати святий Грааль: єдине цілком доступне рішення, при якому, в залежності від запитувачів браузера і пристрої, зображення надсилається ідеально підходящого розміру і дозволу.

Найближче підходить до поняття святого Грааля техніка «clown car»: використання добре підтримуваних медиазапросов, формату SVG і елемента object для подачі адаптивних зображень одним запитом. Це рішення поки неідеально, але вже вдосконалюється.

Фонові зображення і медиазапросы

Ми вирішили проблему адаптивних фонових зображень. Медиазапросы спрощують підгонку розміру і дозволу зображень під растрові співвідношення пристрою, розмір вікна перегляду і навіть орієнтацію екрану. Використовуючи медиазапросы зі стилями свого фонового зображення, можна гарантувати, що з сервера будуть завантажені тільки необхідні зображення. Можна обмежити закачування самими підходящими матеріалами, економлячи пропускну здатність, пам’ять і HTTP-запити.

На жаль, для зображень переднього плану рішення не існувало – до цих пір. Технологія існує вже довгий час. Методика clown car – це просто новинка, яка використовує вже наявну техніку.

Пропоновані за допомогою нової техніки рішення

НОВІ ЕЛЕМЕНТИ І АТРИБУТИ

У випадку з вбудованими або «тематичними» зображеннями трохи складно змусити браузер скачати й відобразити тільки відповідні фонові зображення. Вважається, що механізму, здатного змусити тег img завантажити зображення потрібного розміру і дозволу, не існує. Для цієї мети створені полифилы і сервіси. Був запропонований елемент picture, який користується семантикою елемента HTML5 video з його підтримкою медиазапросов для підкачки різних вихідних файлів:

Техніка Clown Car: зображення в адаптивному вебдизайне

Також був запропонований ще один метод, що використовує атрибут srcset до елементу img. Вищенаведений елемент picture буде записуватися як тут:

Техніка Clown Car: зображення в адаптивному вебдизайне

У цих рішень є достоїнства і недоліки. Вибрати щось одне складно — але нам це не потрібно. Вони обидва були об’єднані в те, що називається компромісом Флоріана (Florian’s Compromise). Однак підтримка ще не зовсім працює. Google запропонував хінти клієнтської сторони як частина заголовка HTTP, щоб подавати потрібні вам зображення серверної стороною.

НЕСПОДІВАНЕ РІШЕННЯ – SVG

Багато хто не знають, що технологія створення та подачі адаптивних зображень, що вже існує. SVG вже тривалий час підтримує медиазапросы, а браузери підтримують SVG … ну, теж досить давно. Більшість браузерів підтримують медиазапросы в SVG (можете протестувати свій браузер). Коли мова йде про адаптивних зображеннях, єдині браузери в мобільному середовищі, які не підтримують SVG – це старі версії На а (підтримка SVG почалася з версії Android 3.0).

Для створення адаптивних зображень ми можемо використовувати браузерну підтримку SVG і SVG-підтримку як медиазапросов, так і растрових зображень, застосовуючи для подачі потрібного зображення медиазапросы в SVG. Мій експеримент теоретично спочатку зобов’язаний працювати – і дійсно працює в Internet Explorer (IE) 10 і Opera. При розмітці HTML ви додаєте до файла SVG єдиний виклик.

Техніка Clown Car: зображення в адаптивному вебдизайне

Простий код, чи не так? SVG підтримують растрові зображення, включені за допомогою елемента image і властивості CSS background-image. У свій адаптивний SVG ми включили б всі зображення, які потрібно доставити, а потім показали б з них на основі медиазапросов тільки відповідне.

СКАЧАЙТЕ ОДНЕ РАСТРОВЕ ЗОБРАЖЕННЯ

Моєю першою спробою в SVG стало застосування image з медиазапросами і приховування їх за допомогою display: none.

Тоді як з точки зору збереження активного стану SVG працює ідеально, у нього є деякі проблеми. На жаль, установка display: none на image в SVG, як і Техніка Clown Car: зображення в адаптивному вебдизайне в HTML, не запобігає від закачування ресурсу. Якщо відкрити SVG image в своєму браузері, всі чотири PNG будуть витягнуті з сервера, зроблено чотири запиту HTTP, дарма витратиться пропускна здатність і пам’ять.

На прикладі фонових зображень CSS ми знаємо, що насправді можлива завантаження тільки потрібних зображень. Точно так само, щоб запобігти закачування всіх включених зображень, у своєму файлі SVG ми б використовували фонові зображення CSS замість зображення переднього плану:

Clown Car Technique
svg {
background-size: 100% 100%;
background-repeat: no-repeat;
}
@media screen and (max-width: 400px) {
svg {
background-image: url(content-1/images/small.png»);
}
}
@media screen and (min-width: 401px) and (max-width: 700px) {
svg {
background-image: url(images/content-1/content-1/images/medium.png);
}
}
@media screen and (min-width: 701px) and (max-width: 1000px) {
svg {
background-image: url(images/big.png);
}
}
@media screen and (min-width: 1001px) {
svg {
background-image: url(images/huge.png);
}
}

Вищенаведений код можна безпосередньо включити як вбудований svg, або вставити за допомогою атрибуту src тега img або атрибута data тега object. Якщо ви знайомі з медиазапросами і CSS, то вищенаведений код зобов’язаний звучати для вас осмислено. Техніка clown car використовує ті ж медиазапросы, які ви застосували б де завгодно у своєму адаптивному вебсайті. Щоб зберегти співвідношення розмірів містить елемента і гарантувати його рівномірне масштабування, ми включаємо атрибути viewbox і preserveAspectRatio.

Значення атрибута viewbox – це список з чотирьох чисел, розділених пропуском або комою: min-x min-y, width і height. Визначаючи ширину і висоту свого паралелепіпеда видимості, ми визначаємо форматне співвідношення зображення SVG. Значення, які ми встановлюємо для атрибута preserveAspectRatio — 300 × 329 — зберігають певну під viewbox співвідношення розмірів.

Проблеми додавання вищеописаного: 1) Chrome і Safari не підтримують співвідношення розмірів, коли svg вбудований: замість цього svg за замовчуванням стає 100% ширини і висоти. Цей дефект був представлений на розгляд. 2) Webkit і Firefox не дозволяють включення растрових зображень або скриптів в SVG, вставлених допомогою елемента img, і 3) підтримка SVG відсутня в IE <=8 і Android <=2.3.3.

При відкритті файла SVG з заданими тільки фоновими зображеннями растрове зображення займе все вікно перегляду. Тоді як версія з image може виглядати краще як окремий файл, тому що підтримує своє співвідношення розмірів, а версія з background-image заповнює вікно перегляду, коли ви включаєте SVG як окремий узятий в HTML документ, співвідношення розмірів зберігається за замовчуванням. Нормально працюють background-size для contain, cover або 100%: виберіть те, що краще всього підходить до ваших вимог.

Властивість CSS background-image вирішує проблему із запитом HTTP. Відкрийте файл SVG з одними фоновими зображеннями PNG (або версію JPEG), подивіться на закладку Мережа (Network) інструменти розробника, і ви побачите, що SVG зробив всього два запиту HTTP, а не п’ять. Якщо у вас великий монітор, то браузер завантажить маленький файл SVG (676 байт) і величезний huge.png або huge.jpg.

Наша перша проблема — закачка всіх розмірів зображень, навіть непотрібних — вирішена. Варіант з background-image завантажує тільки потрібне зображення, беручи, таким чином, заходи до вирішення питання з численними запитами HTTP і марною тратою пропускної здатності.

Чудеса відбуваються при включенні SVG гнучку розмітку. Ви помітите, що при першому ж зміні розміру зображення браузер може моргнути білим, коли запитує наступний потрібний PNG — з-за того, що не автоматично завантажує всі матеріали. Замість цього він завантажує тільки потрібний йому матеріал. Просто заявіть ширину або висоту контейнера (img, svg або object) з допомогою CSS в своїх медиазапросах до розмітки, і SVG витягне єдине потрібне йому растрове зображення.

У нас все ще є сам файл SVG, якому потрібен запит HTTP, коли той не вбудований всередину за допомогою svg. У третю чергу ми вирішимо і цю проблему.

Проблеми безпеки контенту

Відкрийте в Opera або Windows 9 або 10 HTML-файл, що містить растрове зображення SVG, прив’язка до якого зроблена з допомогою тега img. Зверніть увагу на панелі Ресурси (Resources) інструментів розробки, що скачується лише один JPEG або PNG. Змініть розмір браузера. Зауважте, що img — адаптивний. Додаткові JPEG’і чи PNG’і (також можна було б використовувати GIF або WebP) скачується лише коли потрібні.

Якщо відкрити файл HTML, який містить растрове зображення SVG у Firefox є чи WebKit’е, швидше за все, ви не побачите жодного зображення. SVG працює у всіх сучасних браузерах, але img, викликає SVG, який витягує растрові зображення, працює тільки в Opera і IE 9+. Спочатку ми розглянемо, як він працює в IE і Opera, а потім розкриємо проблеми з WebKit’ом і firefox’ом. Код простий:

Техніка Clown Car: зображення в адаптивному вебдизайне

Коли ви включаєте SVG Техніка Clown Car: зображення в адаптивному вебдизайне свого HTML з гнучкою шириною, такий як 70% вікна перегляду, при збільшенні і зменшенні контейнера шляхом зміни розміру вікна або за допомогою CSS зображення буде реагувати відповідно. Медиазапрос width в SVG базується на батьківському елементі, в якому міститься SVG — в даному випадку img — не на ширині вікна перегляду.

По мірі збільшення і зменшення вікна змінюється зображення, що відображається SVG. У файлі SVG зображення визначено, як мають 100% висоти і ширини батьківського елемента, яким у вищенаведеному випадку, коли ми безпосередньо відкрили SVG, було вікно перегляду. Тепер контейнером став елемент img. Так як ми включили атрибути viewbox і preserveAspectRatio, то поки що визначена хоча б одна довжина, SVG буде збільшуватися або зменшуватися відповідно до неї, підтримуючи заявлене співвідношення розмірів в SVG, яким би не був розмір зображення.

Такі зображення переднього плану ідеально працюють в Opera і IE 9+ (у версіях, які можна знайти в мобільних пристроях). У Chrome і Safari, якщо ви спочатку відкриєте файл SVG, таким чином кэшируя його, то HTML-файл, що містить зображення переднього плану SVG, теж може спрацювати.

Тоді як раніше ми бачили, що браузер дійсно може візуалізувати SVG, якщо SVG включений в наш документ допомогою тега img, цей окремий вид SVG не зможе бути відображений. Чому? Для запобігання кроссдоменных скриптових атак в деяких браузерах встановлена стратегія безпеки контенту для того, щоб утримати SVG від імпорту інформації або скриптів на той випадок, якщо вони за своєю природою носять загрозливий характер.

Блокування SVG від імпортування скриптів і зображень має сенс: щоб запобігти кроссдоменные скриптові атаки, вам не потрібно, щоб файл витягував потенційно небезпечний контент. Тому SVG підтримується, але, у випадку з WebKit’ом і firefox’ом, захищається від отримання зовнішніх растрових зображень. Я представив на розгляд звіт про дефект в Chrome, щоб зняти заборону на імпорт растрових зображень в SVG.

У Firefox є адаптивний SVG також працює сам по собі. Firefox повністю підтримує SVG. Проте в цілях безпеки Firefox блокує імпорт зовнішніх растрових зображень, навіть якщо вони знаходяться на одному і тому ж домені. Пояснюється це тим, що можливість відвідувачів вивантажувати, а потім відображати ці зображення і скрипти як частина SVG становить ризик забезпечення безпеки. Я б сказав, що якщо вебсайт використовує небезпечний контент, створений користувачами, то він вже надходить погано. Ця проста рядок…

Техніка Clown Car: зображення в адаптивному вебдизайне

… блокується в деяких браузерах і, таким чином, не є життєздатним рішенням. Всі браузери підтримують медиазапросы SVG. Всі підтримують SVG як зображення переднього плану або «тематичних зображень. Всі вони підтримують SVG як фонові зображення. Просто з-за браузерних стратегій безпеки підтримка не однакова. Всі браузери підтримують тег object. Без зміни браузерних політик безпеки один img ще не буде працювати. Ми можемо застосовувати тег object.

З ДОПОМОГОЮ ТЕГА OBJECT

Елемент object дає зовнішнього ресурсу можливість застосовуватися як зображення. Він може подбати про браузерною безпеки, які ставляться елементу img, не дозволяючи йому імпорт зображень або скриптів в файл img. Елемент object дає можливість робити і те, і інше. Код не дуже складний:

За замовчуванням object буде таким же по ширині, як батьківський елемент. Однак по відношенню до зображень можна заявити ширину або висоту з допомогою атрибуту width або height, або за допомогою властивості CSS width або height. У методиці clown car для підтримки заявленого співвідношення розмірів потрібно просто оголосити одне із значень довжини.
Через заяв viewbox і preserveAspectRatio у файлі SVG за замовчуванням object буде підтримувати заявлений співвідношення розмірів. Переписати його можна за допомогою атрибутів HTML або CSS.

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

З ДОПОМОГОЮ ТЕГА SVG

Замість включення зовнішнього файла SVG можна також включити svg як вбудований контент за допомогою тега svg. Перевага методу – відсутність додаткового запиту http до зовнішнього файлу .svg. На жаль, Chrome і Safari візуалізують SVG як повноекранний блоковий елемент зображення і, схоже, не підтримують атрибут preserveAspectRatio, коли той включений подібним чином вони підтримують preserveAspectRatio,коли SVG включений допомогою тега object).

Ще один недолік полягає в тому, що на відміну від object, ми не можемо включити альтернативний контент для браузерів, які не підтримують SVG. Замість того нам знадобилося б включити background-image з height і width до svg для тих браузерів, які не підтримують SVG.

АЛЬТЕРНАТИВНИЙ ВАРІАНТ ДЛЯ IE

Елемент object підтримується всіма браузерами, навіть мобільними. Але ця техніка працює, тільки якщо браузер підтримує SVG. Отже, вона не працює в IE 8 і нижче або Android 2.3 і нижче. Для цих старих браузерів є альтернативний варіант. Також ми робимо два запити HTTP для отримання потрібного зображення — один для файла SVG і другий для растрового зображення, яке потрібно показати – для цього теж є рішення.

object більш цікавий, ніж img або svg тим, що він – непустий елемент, який може містити альтернативний контент, коли браузер нездатний підтримувати тип даних object. Якщо хочете, для тих браузерів, які не підтримують SVG, можна включити тег img, вкладений в object. Для IE 8 і нижче ми включимо растрове зображення середнього розміру, тому що при нормальному DPI відображаються на моніторах зазвичай вони:

Техніка Clown Car: зображення в адаптивному вебдизайне

На жаль, вміст, вкладене в object, скачується, навіть якщо об’єкт візуалізується і вкладений контент не потрібен або не відображається. Таким чином, додається закачування зображення середнього розміру незалежно від того, потрібна вона чи ні. Щоб справитися з цією проблемою, можна застосувати умовні коментарі для IE.

Техніка Clown Car: зображення в адаптивному вебдизайне

Єдиний запит HTTP

Ми обмежили SVG до закачування одного растрового зображення. Способом object викачуються і растрове зображення, і файл SVG. У нас виходить два запиту HTTP замість одного. Для запобігання додаткових HTTP запитів можна створити URI – уніфікований ідентифікатор ресурсу даних SVG – замість виклику зовнішнього файла SVG.


Техніка Clown Car: зображення в адаптивному вебдизайне

Вищенаведений код здається хаотичним, але коротко це просто data:image/svg+xml, за яким слід вміст файла SVG. Це той самий код, який ми включили б, якщо б користувалися svg контенту, але цей метод підтримує атрибут SVG preserveAspectRatio.

Він працює у всіх браузерах, які підтримують SVG, крім IE. Суцільне розлад, але насправді це із-за того, що Microsoft намагається в точності слідувати специфікації. В ній визначено, що слід уникати URI даних. Тому щоб примусити підтримувати URI даних всі браузери, включаючи IE 9 і 10, ми його уникаємо:

Техніка Clown Car: зображення в адаптивному вебдизайне

Потворна розмітка, але вона працює! Відкрийте першу і другу сторінки, а потім відкрийте інструменти розробки для пильного вивчення запитів HTTP. Ви помітите два запиту HTTP: файл HTML і PNG, який витягує SVG. Інспектор також покаже входження файла SVG. Але зверніть увагу, що ніякого запиту HTTP було зроблено: статус SVG — «success», а розмір над мережею – 0 байт при розмірі уніфікованого індикатора ресурсу даних SVG менше 600 байт.

Альбомна орієнтація проти книжкової

Зазвичай тематичні зображення бувають або в альбомній орієнтації, або в книжковій: особи книжкової, групи людей, товари і сонячні заходи – в альбомній. Деякі сильно заперечують проти техніки clown car, тому що вважають, що зображення не змінюються у відповідності з орієнтацією. Це не обов’язково вірно.

Чари цієї методики в тому, що визуализируемое зображення змінюється в залежності від розміру контейнера. Можна встановити зображення переднього плану в альбомній орієнтації на 33%, або 240 px або що-небудь ще, а ширину об’єкта в книжковій орієнтації на 25% або 180 px або якось ще. Розмір об’єкта визначається CSS до вашого HTML. Подається растрове зображення засноване на медиазапросах, відповідних розміру об’єкта.

Співвідношення розмірів залишається тим же, але ви можете контролювати, яке растрове зображення надається, змінюючи пропорції контейнера SVG, сопоставляющего медиазапросы в CSS вашого HTML з медиазапросами в CSS вашого SVG.

Якщо вам подобається подавати зображення переднього плану в альбомній орієнтації в альбомному режимі і книжкової у книжковому режимі, не користуйтеся атрибутом preserveAspectRatio. Замість цього заявіть в CSS абсолютні висоту і ширину для кожного розміру дизайну з контрольними точками.

Інші переваги

Ще одна перевага техніки clown car полягає в тому, що вся логіка залишається у файлі SVG. Подібно до того, як ми відокремлюємо контент від його презентації та поведінки, цей метод дає нам можливість відокремити логіку зображення від вмісту. Елемент img або object — частина контенту, але логіка, за допомогою якої це все працює, не може бути відокремлена від рівня вмісту: вона знаходиться в зображенні SVG замість засмічення нею CSS і HTML. Ця перевага може спонукати деяких вибрати варіант з URI без даних методу object незважаючи на додатковий запит http, тому що він дуже простий і чистий.

Методика дозволяє нам акуратно організувати свої зображення, відокремлюючи поведінку від презентації, контенту і зображень. Я уявляю собі структуру файлів адаптивного зображення приблизно так:

images/
clowns/
small.png
content-1/content-1/images/medium.png
large.png
svg.svg
cars/
small.png
content-1/content-1/images/medium.png
large.png
svg.svg
techniques/
small.png
content-1/content-1/images/medium.png
large.png
svg.svg

Всі матеріали окремого зображення знаходяться в одній відокремленій директорії. Імена файлу зображення послідовні, тоді як імена папок змінюються. Отримати адаптивні зображення переднього плану можна без засмічення свого HTML додатковим невживаним кодом, полегшуючи таким чином управління зображенням і його оновлення.

Недоліки техніки Clown Car

Ми розкрили доводи «за» цієї методики. Вона все ще перебуває в процесі зародження, тому всі її проблеми не помальовано. Я працюю над вирішенням деяких виявлених питань і передбачаю поява нових складнощів.

Я серйозно цікавлюся тим, чому виникають з методики clown car зображення нездатні вести себе як звичайні PNG’і, JPEG’і і gif’и. Основні зазначені мною проблеми – це порядок завантаження, альтернативний варіант для Android 2.3.3 і нижче, доступність і можливість клацання правою кнопкою по зображенню.

РОЗМІТКА СТОРІНКИ

Згідно Джону Уилкинсу (John Wilkins), методикою clown car потрібно, щоб розмітка CSS повністю візуалізувалася до початку завантаження зображень. У мене не було можливості порівняти завантаження звичайних зображень переднього плану і елемента object з SVG, витягувати растрові зображення, тому поки не можу коментувати вплив цієї проблеми.

ANDROID 2.3 І НИЖЧЕ

Android 2.3 і нижче не підтримує SVG. Я відшукав три можливі рішення, які мені ще належить деталізувати.
SVG background-image Можна використовувати svg як вбудований контент замість object. Тоді як IE 8 і Android 2.3 і нижче не підтримують SVG, з допомогою CSS ці браузери можуть видати розмітку svg з висотою і шириною, а потім заявити растрове зображення як значення background-image.

Так як наша мета – створення адаптивних зображень переднього плану без застосування фонових зображень CSS, цей хак зворотної сумісності нам не підходить. Якщо ми так вирішили, то чому б не застосувати для всіх браузерів і пристроїв фонові зображення CSS замість методики Clown Car?

Умовні коментарі

Спочатку потрібно включити умовні коментарі для включення середньорозмірного альтернативного варіанту для IE 8 і нижче і малоразмерную альтернативу для всіх браузерів, які ігнорують умовні коментарі (включаючи IE 10):

Техніка Clown Car: зображення в адаптивному вебдизайне
—>
Техніка Clown Car: зображення в адаптивному вебдизайне