Досліджуємо проблеми продуктивності адаптивних зображень

11

Від автора: В магазинах продаються пятидюймовые мобільні пристрої з тим же дозволом екрану, що у 50-дюймових телевізорів. У нас є користувачі з необмеженою високошвидкісний широкосмуговий мережею, і є користувачі, які оплачують кожен переданий мегабайт. Адаптивний дизайн зображень означає оптимізацію процесу їх доставки до користувачів. У цій статті ми поділимося своєю методикою адаптивних зображень — «padding-bottom», яку ми вивчили і застосували в мобільній версії шведського новинного сайту Aftonbladet.

Представлені тут методи є результатом кількох тижнів досліджень, зроблених нами в жовтні 2012р. Нам пощастило стати частиною команди, створювала для Aftonbladet новий адаптивний мобільний вебсайт. Aftonbladet – це найбільший шведський сайт, і у його мобільної версії приблизно 3 мільйони користувачів і до 100 мільйонів переглядів на тиждень.

Враховуючи таку кількість користувачів, ми вважали своїм обов’язком створити швидкий і добре оптимізований вебсайт. Економія всього 100 KB образотворчих даних при перегляді сторінки вилилася б у терабайти трафіку, зекономлених у Швеції за рік. Ми почали з вивчення інших технік адаптивних зображень, але так як ні одна з них не підходила нам ідеально, то в результаті ми скомбінували кілька кращих хаків в своє власне рішення. Будь ласка, зверніть увагу, що проект стосувався тільки мобільного адаптивного вебсайту; але не турбуйтеся — наведена тут методика застосовна до всіх видів адаптивних вебсайтів.

Специфікація

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

легко кешуватися,

виконувати мультидоставку зображень.

Давайте пройдемося по цим вимогам і розглянемо, що вони означають.

ЛЕГКЕ КЕШУВАННЯ

Маючи вебсайт, піки трафіку якого налічують понад 10 000 запитів в секунду, нам хотілося зберегти внутрішню логіку наскільки простий. Це означає, що нам потрібна детекція пристроїв на серверній стороні або рішення на основі куки, що поставляє множинні версії HTML. Нам хотілося завдавати всім користувачам єдиний файл HTML, хоча було прийнятно маніпулювання HTML за допомогою JavaScript’а після його завантаження. Ті ж правила застосовувалися до зображень; потрібна була можливість викладати зображення в мережі доставки контенту (CDN), а в логіці доставки зображень не потрібно було ніякої динаміки.

МУЛЬТИДОСТАВКА ЗОБРАЖЕНЬ

Ми хотіли доставляти різні версії зображення на різні пристрої. Однією з серйозних скарг на попередній мобільний вебсайт було та, що високощільні iphone’ов и і пристрої Android не отримували гідних зображень у високому дозволі. Отже, нам потрібно поліпшити якість зображень, але лише для тих пристроїв, які були здатні їх відобразити.

Завантаження зображень з допомогою JavaScript’а

JavaScript, будучи поміщеним в нижній колонтитул, де йому саме місце, буде завантажуватися після аналізу HTML і CSS. Це означає, що якщо JavaScript несе відповідальність за завантаження зображень, то ми не можемо користуватися перевагою браузерного засоби попереднього завантаження, і тому зображення почне завантажуватися набагато пізніше звичайного. Звичайно, це недобре, і при цьому оголюється інша проблема: сторінка може перерисовываться кожного разу при вставці JavaScript’ом зображення в DOM.

Повторна оновлення відбувається, коли браузер перераховує розміри елементів на сторінці та перемальовує їх. Ми встановили демо-сторінку і відеоролик, що демонструє цей ефект. Зауважте, що в демо-сторінку вставлена затримка в 500 мілісекунд між кожним зображенням для імітації низької швидкості з’єднання.

Як видно з відеоролика, ще дуже дратує те, що користувач напевно загубиться в перемальовуванні при поверненні на сторінку за допомогою кнопки «Назад» («Back»). Це дійсно серйозна проблема для таких вебсайтів, як Aftonbladet. Наявність функціональної кнопки «Назад» утримає користувачів на сайті на більш тривалий час.
Насправді проблеми перемальовування не буде на неадаптивном вебсайті, тому що ми зможемо встановити до тегу зображення ширину і висоту в пікселях:

Досліджуємо проблеми продуктивності адаптивних зображень

Одним з важливих аспектів адаптивного вебдизайну є видалення таких жорстко запрограмованих атрибутів і створення гнучких зображень за допомогою CSS:

img {
max-width: 100%;
}

Немає більше max-width: 100%

Нам потрібно було відшукати рішення, за допомогою якого ми могли б приберегти місце для зображення з допомогою одного HTML і CSS і, таким чином, уникнути повторної заливки. Тобто, коли JavaScript для вставлення зображення на сторінку, воно буде вставлена тільки в призначену область, а ми уникнемо перезаливки. Отже, ми відкинули один з кутових каменів адаптивного дизайну, img { max-width: 100% }, і стали шукати інше рішення, яке могло б резервувати місце для адаптивного зображення. Нам потрібно було щось, що визначає тільки розмірне співвідношення зображення і дозволяє висоті зменшуватися разом з шириною. І ми відшукали таке рішення.

Хак Padding-Bottom

Ця техніка заснована на чомусь з назвою intrinsic ratios (вбудовані пропорції), але чого жоден член нашої команди не міг пригадати, зрозуміти або вимовити термін «intrinsic», і ми просто назвали його хаком «padding-bottom».

Багато дізналися про цю властивість у 2009р. в статті A List Apart «Створення вбудованих пропорцій для відео» автора Террі Коблегца (Thierry Koblentz), і ця техніка часто вживається в адаптивних вебсайтах для вставки стороннього вмісту і медіа. З допомогою цієї техніки ми визначаємо висоту як міру, відносну до ширини. У padding та margin є такі вбудовані властивості, і ми можемо користуватися ними для створення співвідношень розмірів для елементів, які не містять у собі контенту.

Так як у padding є ця здатність, можна встановити padding-bottom так, щоб він був відносний ширині елемента. Якщо також встановити висоту на 0, вийде якраз те, що нам потрібно.

.img-container {
padding-bottom: 56.25%; /* співвідношення 16:9 */
height: 0;
background-color: black;
}

Наступний крок – помістити зображення всередині контейнера і переконатися, що воно заповнює його. Щоб це зробити, потрібно позиціонувати зображення всередині контейнера абсолютно, як тут:

.img-container {
position: relative;
padding-bottom: 56.25%; /* співвідношення 16:9 */
height: 0;
overflow: hidden;
}
.img-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

Досліджуємо проблеми продуктивності адаптивних зображень

У контейнері резервується необхідне місце для зображення.

Тепер можна підлаштувати свій демо-приклад, застосувавши хак padding-bottom, і користувач більше не заблукає в перерисовках, як це було раніше. Крім того, кнопка «Назад» («Back») функціонує так, як їй належить. Дивіться новий відеоролик і демо.

Ця техніка покращує враження користувача від вебсайті чистіше традиційного підходу max-width, але досвідчений читач вже звернув до цього моменту увагу на кілька наступних моментів:

Перед завантаженням зображення нам потрібно знати його формат.

Зображення можна масштабувати більше їх початкового розміру.

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

На Aftonbladet ми вирішили вважати процентне співвідношення padding-bottom на сервері і виводити його в HTML як вбудований стиль, як ви побачите в наступних фрагментах коду. Щодо другої проблеми ми виявили, що в нашому випадку набагато краще дати можливість зображенню масштабуватися при необхідності (і втратити в якості), ніж встановити фіксовану максимальну ширину зображення.

Вибір способу завантаження зображення

Тепер, коли ми дозволили собі завантажувати зображення з допомогою JavaScript’а, так як мінімізували перезалиття, можна встановити до нього вимоги:

Остаточний HTML повинен бути одним тегом img.

Елементи DOM повинні бути мінімальні.

Виконуватися все має як можна швидше.

Не повинна руйнуватися при відключеному JavaScript’е.

На підставі цієї простої специфікації ми створили вбудований нескладний JavaScript, базується на техніці noscript. Ідея полягає в тому, щоб додавати інформацію про різних розмірах зображення в HTML в якості атрибутів даних тега noscript. Вмістом тега noscript стане тег img, і буде показуватися в браузерах з вимкненим JavaScript’ом. Давайте подивимося на розмітку:

Досліджуємо проблеми продуктивності адаптивних зображень

Тоді робота JavaScript’а полягає в аналізі вмісту сторінки, визначенні тих зображень, які потрібно піддати «ледачою» завантаженні, перевірці розміру екрану пристрою і підборі відповідного зображення. Наступний код буде шукати зображення для завантаження і вставки в DOM. Важливо, щоб JavaScript був вбудований і завантажувався як можна швидше після HTML. Скрипт також буде повертати тег alt з тега noscript і вставляти його в свіжостворений тег img.

var lazyloadImage = function (imageContainer) {
var imageVersion = getImageVersion();
if (!imageContainer || !imageContainer.children) {
return;
}
var img = imageContainer.children[0];
if (img) {
var imgSRC = img.getAttribute(«data-src-» + imageVersion);
var altTxt = img.getAttribute(«data-alt»);
if (imgSRC) {
var imageElement = new Image();
imageElement.src = imgSRC;
imageElement.setAttribute(«alt», altTxt ? altTxt : «»);
imageContainer.appendChild(imageElement);
imageContainer.removeChild(imageContainer.children[0]);
}
}
},
lazyLoadedImages = document.getElementsByClassName(«lazy-load»);
for (var i = 0; i < lazyLoadedImages.length; i++) {
lazyloadImage(lazyLoadedImages);
}

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

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

При виборі оптимального зображення для передачі на певний пристрою слід враховувати безліч чинників, таких як розмір екрана, швидкість мережі, здатність до кешуванню, загальна вага сторінки та уподобання користувача. Вебсайт, побудований нами для Aftonbladet, в основному призначений для мобільних браузерів, і нам сильно пощастило, тому що була велика кількість статистики про поведінку середнього користувача. Аналізуючи цифри, ми змогли окреслити кілька тенденцій.

По-перше, переважна більшість тримають свій пристрій в книжковій орієнтації. Для читання та перегляду статей книжкова орієнтація підходить відмінно. І хоча розміри екранів сильно розрізняються, більше 99% проаналізованого нами трафіку являє пристрою ширини області перегляду або 320, або 360 px.

По-друге, у більшості відвідують сайт пристроїв високощільні екрани з вихідної шириною в 480, 640, 720 або 1080 px. Саме високий дозвіл – у нових телефонів, таких як Galaxy S4 і Xperia Z; тоді як зображення шириною 1080 px на них виглядає відмінно, тести показали, що зображення шириною в 720 px теж виглядало б досить добре, споживаючи при цьому менше пропускної здатності.

Після аналізу даних ми зупинилися на трьох версіях кожного зображення:

Маленьке (small) (оптимізоване для екрану шириною 320 px),

Середнє (medium) (оптимізоване для екрану шириною 640 px),

Велике (large) (оптимізоване для екрану шириною 720 px).

(Пристрою без JavaScript стануть отримувати маленьке зображення). Ми вважаємо ці установки розумними для мобільного вебсайту, але повністю адаптивний веб-сайт, призначений для всіх типів пристроїв, можливо, виграє від різних установок.

Версіям ми даємо логічні імена замість визначення медиазапросов в розмітці. Це зроблено в ім’я гнучкості. Так буде простіше розвивати JavaScript у майбутньому, скажімо, адаптації до швидкості мережі або створення можливості для користувача встановити скасування того, яке зображення використовувати. У найпростішому вигляді движок відбору версій зображення можна реалізувати, як у наступному прикладі (хоча для підтримки Internet explorer’а нам знадобиться інша функція як обхідного маневру з-за відсутності window.devicePixelRatio).

var getImageVersion = function() {
var devicePixelRatio = getDevicePixelRatio(); /* Функція де визначено.*/
var width = window.innerWidth * devicePixelRatio;
if (width > 640) {
return «high»;
} else if (width > 320) {
return «medium»;
} else {
return «small»; // версія
}
};

Також при відборі відповідного зображення ми намагалися взяти до уваги висоту екрану. Теоретично було б чудово переконатися, що зображення добре підходить пристрою. Але при тестуванні теорії на практиці незабаром було виявлено занадто велика кількість крайніх випадків, зробили визначення висоти досить підходящим способом неможливою.

Додатки, які впроваджують веб-огляди, відзвітували про порівняльному випадковому розкиді висоти від 0 до 3000 px, а такі функції, як система TouchWiz від Samsung, у якої є режим поділу екрана, змусили нас відкинути висоту екрану як надійне значення при виборі розмірів зображення.

Ми створили просту демо-сторінку, де є весь потрібний JavaScript і CSS. Але пам’ятайте, що наш код призначений для мобільних пристроїв, тому не працює добре, скажімо, старих браузерах Internet Explorer.

Робимо зображення менше

Великі красиві зображення витрачають багато пропускної здатності. Скачати безліч зображень шириною в 720 px в мобільній мережі і займе багато часу, і дорого обійдеться користувачеві. Хоча новий формат зображення, такої як WebP, може допомогти деяким користувачам, але він не підтримується достатньою кількістю браузерів, щоб бути життєздатним в якості єдиного рішення. На щастя, завдяки дослідженню Даана Джобсиса (Daan Jobsis) ми можемо скористатися тим фактом, що високий рівень стиснення не надто впливає на сприймається якість зображення, якщо розміри зображення більше відображуваних, або якщо зображення показується у його натуральну величину на высокоплотном екрані.

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

Це також причина того, чому ми не включили версію зображення для екранів в 480 px. Зменшення масштабу зображення шириною 640 px з високим рівнем стиснення вело до одержання краще баченого зображення меншого розміру, ніж ми могли домогтися від зображення з вихідним дозволом екрану 480 px. В такому випадку, вирішили ми, варто змусити пристрій масштабувати зображення так, щоб воно підходило.

ЧЕРВОНІ ОБЛАСТІ ДОБРЕ НЕ СТИСКАЮТЬСЯ

Однак високий рівень стиснення – не панацея. Деякі зображення, будучи стислими, виглядають жахливо, особливо ті, у яких є помітні яскраво-червоні області, де спотворення при стиску JPEG стануть чітко видимими і зможуть зіпсувати загальне враження від нього. На жаль, редактори Aftonbladet захоплюються зображеннями з помітними яскраво-червоними областями, що дещо ускладнило нашу задачу.

Досліджуємо проблеми продуктивності адаптивних зображень

Два цих зображення збережено з установкою якості на 30% . Тоді як зображення зліва може задовільно виглядати навіть на звичайному екрані, червона окружність на правому виглядає погано навіть на высокоплотном екрані.

ПОШУК КОМПРОМІСУ

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

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

Досліджуємо проблеми продуктивності адаптивних зображень

Зображення-тизери на сторінках Aftonbladet (ліворуч) дійсно відмінно працюють при високому рівні стиснення, тоді як повноекранна галерея зображень (праворуч) користується всіма перевагами високоякісних зображень.

Генерація різних зображень може виявитися проблемою. Ми користуємося розкішшю вже наявного серверного рішення, яке здатне масштабувати, стискати і обрізати зображення на вимогу. Запуск вашого власного може спричинити багато роботи, але його реалізація, наприклад, плагіна WordPress (застосовуючи клас WP_Image_Editor) дійсно стане просуванням вперед.

Висновок

Три роки минуло з моменту подання Ітаном Маркоттом (Ethan Marcotte) адаптивного вебдизайну, а ми все ще намагаємося відшукати хороше рішення проблеми керування зображеннями. Всі адаптивні рішення є більшою чи меншою мірою хаком, і вищеописане – не виняток. Але нам вдалося уникнути проблеми надмірної повторної заливки, ми не виробили безлічі непотрібних елементів DOM, наш вебсайт піддається кешуванню, і ми запобігаємо завантаження невикористовуваних зображень.

На домашній сторінці Aftonbladet для мобільних пристроїв є близько 40 зображень і, з допомогою цієї техніки, вона в підсумку важить приблизно 650 KB на «великому екрані», 570 KB на середньому і 450 KB на маленькому (хоча розмір змінюється в відповідності з вмістом). Без сильного стиснення великі і середні версії будуть за розміром більше мегабайта. А в порівнянні зі старим вебсайтом нам вдалося перейти від розмитих зображень в низькому дозволі на високоякісним, підігнаних під кожен пристрій, отримавши при цьому лише 25% збільшення розміру закачування.

Отже, ми все ще чекаємо ідеального рішення адаптивних зображень. Тим часом все вищенаведене стало вдалим рішенням для нового адаптивного вебсайту Aftonbladet і гібридних додатків. Новий вебсайт (чиє сприймане час завантаження зменшилася вдвічі в порівнянні з попереднім) призвів до величезного вибуху трафіку і взаємодії користувачів; і все літо трафік мобільної версії Aftonbladet залишався вище трафіку настільної і планшетній версії.