Небольшой эксперимент с использованием data: URL

Владимир | | CSS, HTML, Web разработка.

data uri

В последнее время всё больше внимания уделяется клиентской оптимизации сайтов. Я не могу сказать, что раньше ею никто не занимался, скорее, наоборот, с появлением широкополосного доступа к Internet часть проблем решилась сама собой. Но появление новых технологий, предоставляет новые возможности, которыми имеет смысл пользоваться.

К сожалению, не всегда есть возможность проигнорировать устаревшие браузеры (главным образом речь идет о IE6 и 7). И это сильно замедляет использование новых стандартов.

Ситуация довольно сложная. Большинство владельцев ресурсов не согласятся потерять часть аудитории (пусть даже небольшую) только потому, что разработчик решил внедрить новую технологию. Но не все понимают, что использование устаревших технологий делает менее комфортной работу посетителей с нормальными браузерами. В частности, время загрузки страницы для них окажется больше, чем могло бы быть.

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

Об одной из таких технологий и пойдёт речь в этой статье. Называется она data: URL.

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

Для себя задачу я ставил достаточно просто. Проверить, насколько сложно будет обеспечить одинаковый вид страницы во всех браузерах, начиная с IE6.

Сразу выкладываю ссылку на архив с примером, который я использовал для экспериментов.

Source

Рассмотрим тестовую страницу

<!DOCTYPE html>

<html>
<head>
    <title>CSS clip</title>
    <meta charset="utf-8" />
</head>

<body>

<div id="social_icons">
    <a href="#" class="twitter icon"></a>
    <a href="#" class="facebook icon"></a>
    <a href="#" class="bobrdobr icon"></a>
    <a href="#" class="memori icon"></a>
    <a href="#" class="delicious icon"></a>
    <a href="#" class="stumbleupon icon"></a>
</div>

</body> </html>

Она содержит шесть ссылок, которые нужно показать в виде иконок на социальные сервисы.

Делается это достаточно просто. Для каждой ссылки задаётся ширина, высота и фоновое изображение (иконка).

При этом браузер загрузит каждый файл, который будет указан в свойстве background-image. Т.е. если у нас шесть иконок, то будет отправлено шесть запросов серверу. Учитывая, что размеры иконок редко превышают несколько кБ, загружать их по одной не выгодно.

Наиболее распространённым методом оптимизации в таких случаях является использование CSS спрайтов. При этом все картинки объединяются в одну, а нужный фрагмент показывают с помощью свойства background-position.

Именно этот вариант я решил использовать для браузеров IE6 и 7, а для новых – передать иконки с помощью data: URL.

Подготовка данных для использования в data: URL

Тут всё достаточно просто. Нужно закодировать содержимое файла с картинкой с помощью base64 и вставить полученную строку в CSS файл.

В моем случае, исходное изображение выглядит следующим образом.

icons sprites

Примечание. Я использовал коллекцию бесплатных иконок от wpzoom.

На практике можно воспользоваться одним из сервисов, выполняющих эту операцию. Например, duris.ru или dopiaza.org.

В результате у меня получилась такая таблица стилей.

@charset 'utf-8';

.icon {
	width: 64px;
	height: 64px;
	display: block;
	float: left;
	margin: 10px;
}

div#social_icons a {
	background-image: url("data:image/png;base64,iVBORw......");
	background-repeat:no-repeat;
}
.twitter {
	background-position: 0 0;
}
.facebook {
	background-position: 0 -64px;
}
.bobrdobr {
	background-position: 0 -128px;
}
.memori {
	background-position: 0 -192px;
}
.delicious {
	background-position: 0 -256px;
}
.stumbleupon {
	background-position: 0 -322px;
}

Обратите внимание. Здесь не важно кодируете вы один файл со всеми иконками или каждую отдельно. Все данные будут переданы внутри CSS файла.

Рассмотрим стили подробнее.

Для каждой ссылки мы указываем высоту (width) и ширину (height). При этом, нужно сделать ссылку блоковым элементом (display: block), иначе длина и высота применятся не будут. Чтобы расположить иконки в один ряд, используем обтекание (float: left).

Далее каждой ссылке устанавливаем фоновое изображение (background-image). В качестве значения url вставляем результат преобразования картинки. Я его сократил, т.к. он занимает около 19 кБ.

Затем с помощью background-position показываем нужный фрагмент картинки. В данном случае все иконки имеют размер 64х64 px и расположены вертикально, поэтому просто изменяем вертикальную координату на 64 px.

Остаётся подключить файл стилей к странице.

<link rel="stylesheet" type="text/css" href="styles.css" />

Всё. В современных браузерах иконки отображаются правильно.

Для формирования страницы браузер выполняет два запроса к серверу. Первый – получение самой страницы, второй – получения файла стилей. При этом, файл стилей занимает 19,1 кБ (если его сжать, получится 14,4 кБ).

Поддержка IE6 и 7

Есть несколько вариантов решения этой задачи. Подробно они рассмотрены в статье Кроссбраузерное использование data:URL.

Я покажу один из самых простых вариантов, с заменой файла стилей.

Идея предельно простая. С помощью условных комментариев, браузерам IE6 и 7 указываем свой собственный CSS файл.

Выглядит это следующим образом.

<!--[if lt IE 8]><link rel="stylesheet" type="text/css" href="ie_6_7_styles.css" /><![endif]-->
<!--[if gte IE 8]><link rel="stylesheet" type="text/css" href="styles.css" /><![endif]-->
<!--[if !IE]>--><link rel="stylesheet" type="text/css" href="styles.css" /><!--<![endif]-->

В результате, современные браузеры загрузят файл styles.css, а шестая и седьмая версии IE – ie_6_7_styles.css.

В этих стилях отличается только свойство background-image. Вместо data:URL указываем файл с иконками.

div#social_icons a {
    background-image: url("icons/icons_sprites.png");
    background-repeat:no-repeat;
}

Теперь во всех браузерах иконки отображаются одинаково.

Результаты

Должен отметить, что в данном случае, результаты получились не очень впечатляющие.

Безусловно, при использовании data: URL количество запросов уменьшилось (на один), но объём передаваемых данных увеличился практически на 5 кБ (исходный файл icons_sprites.png «весит» 13,9 кБ, а после base64 преобразования он занимает около 19 кБ).

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

Кроме того, усложняется процесс обновления картинок, т.к. они будут кешироваться вместе с CSS файлом. (Эта проблема решаемая, но выходит за рамки данной статьи).

С другой стороны, в этой статье рассмотрен очень простой пример. Для сложного сайта файлов со спрайтами может получиться довольно много и в этом случае эффект от использования data: URL будет выше за счёт уменьшения количества запросов.

К тому же, если бы не нужна была поддержка IE6, 7, то можно было бы вообще не заниматься созданием файла со спрайтами и установкой background-position, а просто передавать изображения в background-image для соответствующих элементов.

В целом, я не уверен, что в ближайшее время начнется массовое использование data: URL. Тем не менее, технология очень интересная.

Успехов!

Интересно почитать

Хотите сделать карьеру в IT? Курсы программистов будут хорошей стартовой точкой.

Нужна декларация 3-ндфл «продажа квартиры»? Заполним за сутки и вышлем на емейл.

  • alert

    Как на меня, это уже за гранью фанатизма

    • Возможно именно эта технология действительно не получит широкого распространения. Но web приложения меняются и нужно привыкать 😉

    • сам гугл юзает эту тему!

      • Google — не самый характерный пример 🙂
        С их нагрузкой даже минимальная оптимизация будет очень ощутимой.

  • > исходный файл icons_sprites.png «весит» 13,9 кБ, а после base64 преобразования он занимает около 19 кБ

    А как насчет gzip сжатия?

    • Эффект будет, но очень небольшой, около 20%, т.е. получается примерно 15кБ. Дело в том, что основную часть CSS файла занимает картинка в png формате, т.е. уже сжатая.

  • хм, интерестній пост

  • Dmitry Maltsev

    Выигрышь заметен не на одном спрайте, а когда в CSS шьётся много графики. Серверное сжатие полностью нивелирует возрастание трафика от раздувшегося байт-кода. Если присмотреться, каждый data:url имеет повторяющиеся участки, которые при архивации будут слиты в один.