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

Пятидюймовые мобильные устройства, которые на сегодняшний день существуют на рынке, имеют разрешение экрана аналогичное 50-ти дюймовым телевизорам.

Существует две категории пользователей: с неограниченным, высокоскоростным широкополосным доступом, а также те, которые платят деньги за каждый полученный мегабайт данных. Адаптивный дизайн для изображений – это оптимизированный для пользователей процесс функционирования изображений. В этой статье мы поделимся нашей техникой создания адаптивных изображений, а также техникой “нижнего заполнения”. Описанные методы мы исследовали и реализовали для мобильной версии шведского веб-сайта новостей Aftonbladet.

Методы, представленные здесь, являются результатом нескольких недель исследований, которые мы проводили в октябре 2012 года. Нам очень повезло стать частью команды, которая должна была создать новый мобильный адаптивный веб-сайт для Aftonbladet. Aftonbladet является крупнейшим сайтом Швеции, а его мобильная версия должна была получить около 3 миллионов уникальных пользователей и до 100 миллионов просмотров страниц в неделю.

Зная о таком невероятном количестве пользователей, мы чувствовали огромную ответственность и необходимость создать быстрый, хорошо оптимизированный сайт. Сохранение на странице всего лишь 100 килобайтного изображения за год перерастет в терабайты трафика данных. Мы начали с исследования других методов создания адаптивных изображений. Поскольку ни один из методов не работал идеально, мы решили объединить некоторые из них и создать наше собственное решение. Пожалуйста, обратите внимание на то, что этот проект охватывает только адаптивный мобильный веб-сайт; но не волнуйтесь — методы, представленные здесь, относится ко всем типам адаптивных веб-сайтов.

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

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

  • Легкость кэширования,
  • многоканальное обслуживание изображений.

Давайте пройдемся по этим требованиям и посмотреть, что они значат.

Легкость кэширования.

Для сайта, который получает пиковый трафик более 10000 запросов в секунду, мы хотели создать как можно более простую серверную логику. Это означает, что мы не хотим использовать серверные устройства обнаружения или решения на основе куки-файлов, которые обслуживают несколько версий HTML. У нас была необходимость только в одном HTML файле, который будет использоваться для всех пользователей, хотя манипулирование HTML с помощью JavaScript после загрузки является приемлемым вариантом. Те же правила применяются и к изображениям. У нас должна быть возможность разместить изображения в сети доставки контента (CDN), и мы не хотели бы получить какую-либо динамику в порционной логике передачи изображения.

Многоканальное обслуживание изображений.

Мы хотели обеспечить возможность предоставления различных версий изображения для различных устройств. На наш предыдущий мобильный веб-сайт поступила одна большая жалоба, суть которой заключалась в том, что iPhone и Android устройства с высоким разрешением экрана (DPI) не получали изображения соответствующего качества. Именно поэтому мы хотели улучшить качество изображений, но только для устройств, которые были способны их отображать.

Загрузка изображений с помощью JavaScript.

Если JavaScript поместить в нижнем колонтитуле, то он будет загружаться после HTML и CSS. Это означает, что, если JavaScript отвечает за загрузку изображений, мы не сможем воспользоваться предварительной загрузкой браузера, и как следствие, загрузка изображения начнется немного позже, чем обычно. Естественно, что подобная модель загрузки неправильна и к тому же возникает и другая проблема: страница может выполнять переформатирование каждый раз, когда JavaScript вставляет изображение в DOM.

Переформатирование происходит, когда браузер пересчитывает размеры элементов на странице и обновляет их. Мы создали демо страницу и видео, которые демонстрируют этот эффект. Обратите внимание, что на демо-странице используется задержка в 500 миллисекунд для каждого изображения. Это необходимо для имитации медленной скорости соединения.

Как вы можете видеть на видео, еще одна очень раздражающая особенность заключается в том, что пользователь, скорее всего, запутается от перезагрузки при возвращении на страницу с помощью кнопки “Назад”. На самом деле, для таких сайтов как Aftonbladet это довольно серьезная проблема. Веб-сайты, имеющие функциональную кнопку “Назад”, увеличивают время нахождения пользователей на сайте.

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

<img src="img.jpg" width="60" height="60"/>

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

img {max-width: 100%;}

Исключение max-width: 100%.

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

Метод «нижнего заполнения».

Метод “нижнего заполнения” основан на так называемых внутренних коэффициентах. Поскольку ни один из членов нашей команды не мог вспомнить, понять и произнести термин “intrinsic” (внутренний) мы просто назвали его «нижним заполнением».

Многие люди узнали об этой функции еще в 2009 году в A List Apart в статье “Создание внутренних коэффициентов для видео” от Тьерри Коблентца, а техника часто используется на адаптивных веб-сайтах для внедрения стороннего контента и медиа ресурсов. Данный подход основан на определении высоты в качестве меры по отношению к ширине. Заполнение и поля обладают внутренними свойствами, и мы можем использовать их для создания пропорций элементов, которые не имеют никакого содержимого.

Заполнение имеет такую возможность, что мы можем установить значение padding-bottom относительно ширины элемента. Если мы при этом устанавливаем высоту равную 0, то мы получим именно то, что мы хотим.

.img-container {
	padding-bottom: 56.25%; /* 16:9 ratio */
	height: 0;
	background-color: black;
}

Следующим шагом является размещение изображения внутри контейнера. При этом нужно убедиться, что оно заполняет контейнер. Чтобы сделать это, нам нужно выбрать абсолютное размещение изображения внутри контейнера, вот так:

.img-container {
	position: relative;
	padding-bottom: 56.25%; /* 16:9 ratio */
	height: 0;
	overflow: hidden;
}

.img-container img {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
}

Контейнер резервирует пространство, необходимое для изображения.

Теперь мы можем настроить наше демо, применяя метод «нижнего заполнения», и пользователи уже больше не будут вводиться в заблуждение переформатированием, подобно тому, что мы видели ранее. Кроме того, кнопка “Назад” функционирует как и ожидалось. Смотрите новые видео и демо.

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

  1. Прежде чем загрузить изображение, мы должны узнать соотношение сторон изображения.
  2. Изображения могут быть расширены больше оригинального размера.

Для работы с пропорциями, нужно либо иметь систему управления контентом, с помощью которой вы можете управлять шаблонами или иметь ограниченный, фиксированный набор пропорций для изображений. Если у вас есть какой-то промежуточный метод, то его будет очень трудно использовать в силу того, что вы не сможете влиять на визуализацию тегов изображения.

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

Выбор способа загрузки изображения.

Теперь, когда мы минимизировали переформатирование, можно позволить себе загружать изображения с помощью JavaScript. Мы можем установить определенные требования этой процедуре:

  • Результирующий HTML должен быть в едином img теге.
  • Использование DOM элементов должно быть минимальным.
  • Операции должны выполняться настолько быстро, насколько это возможно.
  • Загрузка не должна прерываться при отключении JavaScript.

На основе этой простой спецификации, мы создали встроенный унифицированный JavaScript код, основанный на “NoScript” технике. Идея состоит в том, чтобы добавлять информацию о различных размерах изображения в HTML, как атрибуты данных в noscript тег. Содержимым noscript тега будет img тег и будет отображаться в браузере, в котором отключен JavaScript. Давайте посмотрим на разметку:

<noscript data-src-small="img-small.jpg" 
    data-src-medium="img-medium.jpg" 
    data-src-high="img-high" 
    data-src-x-high="img-x-high.jpg">
        <img src="img-small.jpg">
</noscript>

Основная задача 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 ...

Если вы хотите прочитать полностью статью, посетите сайт наших спонсоров

Comments are closed.