Про CSS-спрайты сейчас пишут много и везде, но, как правило, все ресурсы перемалывают одну и ту же идею: сохранение кучи мелких картинок в одну для увеличения общей скорости загрузки сайта. В этой статье из двух частей я попробую собрать все свои знания по этой теме и продемонстрировать некоторые особенности применения спрайтов в вебе.
Что такое спрайты?
Думаю, вы и без меня знаете, что это такое. Спрайты — это несколько небольших картинок, объединенных в один графический файл.
Такой подход дает сразу несколько преимуществ. Во-первых, объем одного файла как правило меньше, чем сумма объемов отдельных файлов. Это можно объяснить снижением издержек на сохранение одного изображения: всякие там заголовки, указывающие на формат изображения, или общая палитра цветов, если речь идет об индексированном PNG или GIF. Бородатые кодеры могут вспомнить рекомендации 90-х годов по разбивке одного большого файла на несколько мелких, чтобы создать иллюзию у пользователя, что сайт грузится быстрее 🙂 Такой подход создавал именно иллюзию, так как суммарный объем нескольких файлов был больше, чем объем одного файла, а сама картинка грузилась дольше.
Во-вторых — самое главное — сокращается количество HTTP-запросов к серверу. Некоторые ребята не обращают на это внимание, а зря: зачастую отдельный запрос обходится намного дороже, чем десяток «лишних» данных в одном изображении. Не буду подробно расписывать этот момент, так как это тема для отдельного разговора.
Итак, мы уже знаем, что спрайты — это круто и модно. Ограничено ли применение спрайтов только группировкой разных изображений в одно?
Назад в прошлое
Будучи неопытным юнцом, я очень любил играть в игры. Больше всего меня интересовало то, как же эти игры делаются. Тогда еще не было повсеместного использования 3D-графики, все игры, в которые я играл, в основном были 2D-аркадами (Another World, Commander Keen, Moles, Prince of Persia, эх…), активно использующими спрайты. Вообще, слово «спрайт» получило широкое распространение именно благодаря видеоиграм, и именно видеоигры больше всего повлияли на меня как на веб-разработчика.
Помимо обычной группировки изображений можно выделить еще несколько типов спрайтов.
Раскадровка
Раскадровка, по сути, представляет собой набор кадров для анимации, сохраненных в одном файле. Для такого спрайта пишется контроллер на JavaScript, который управляет скоростью и направлением смещения спрайта. По сравнению с обычной GIF-анимацией это дает нам следующие преимущества:
- Можно использовать JPEG или полупрозрачный PNG.
- Более широкие возможности по оптимизации изображения.
- Можно самостоятельно управлять скоростью и направлением анимации, имея один и тот же набор кадров (то есть используя всего одно изображение).
При создании такого спрайта нужно помнить следующее. Для начала нужно выбрать размер кадра; такой, чтобы в нем без проблем уместилась любое изображение из раскадровки +10-20% свободного пространства по бокам для надежности. Это позволит в дальнейшем без особых хлопот модифицировать изображение.
Затем нужно точно совместить изображения в кадрах, чтобы при анимации не были заметны рывки. Если все сделаете правильно, то на создание JS-контроллера уйдет минимум сил и времени.
Циклический спрайт
Этот тип спрайтов в основном применяется для создания механизмов наподобие прелоудера: некая повторяющаяся текстура на блоке неопределенной ширины.
Тут, конечно, руки так и чешутся использовать GIF-анимацию, однако перфекционистов вроде меня может не устроить плавность движения. Сравните:
В первом случае я сделал GIF-анимацию с задержкой 0 ms (то есть вообще без задержки) между кадрами. В предпросмотре фотошопа все работает довольно плавно, а в браузере отчетливо заметны задержки между кадрами. В JS-анимации, используя контроллер из предыдущего примера, задержек никаких нет.
К минусам данного подхода можно отнести более высокие требования системным ресурсам, поэтому если у вас много прелоудеров на странице нужно десять раз подумать, что лучше использовать, GIF или JS.
Слои
Иногда случается так, что для изображения не получается выбрать самый оптимальный формат. Наиболее яркий пример — фотография с полупрозрачными декорациями:
В этом случае намного эффективнее будет разделить изображение на два слоя: первый — сердцевина — сохранить в JPEG, а второй — окантовка — в полупрозрачный PNG.
Таким образом мы убиваем сразу двух зайцев: снижаем вес изображения и улучшаем его качество, используя для каждого слоя наиболее подходящий формат.
Естественно, этот пример довольно простой и примитивный: уверен, что многие так и поступили бы с этой картинкой. Наибольший эффект от такого типа спрайтов достигается в том случае, когда сердцевина имеет не прямоугольную форму. Хороший пример: раздел «Отделение Imperia» сайта Imperia Private Banking:
Огромный узор на двери был разделен на 2 слоя: сердцевину и окантовку, каждый слой был по-своему оптимизирован, что в итоге позволило мне сэкономить около 200 КБ. Как быстро разделить изображение на два таких слоя я писал в статье «Про PNG. Часть 2».
Векторные маски
К сожалению, не всегда подобные картинки можно эффективно разделить по слоям. Например, когда сердцевина не прямоугольной формы содержит фотографическое изображение. В этом случае на помощь приходят современные браузерные технологии, а именно SVG, Canvas и VML. С помощью них можно наложить векторные маски на прямоугольную JPEG-картинку, добившись необходимого внешнего вида. Для этих целей я написал специальную библиотеку под названием ictinus, которая занимается решением таких задач. Хороший пример использования использования спрайтовых масок (и моей библиотеки :)) — главная страница сайта «Аймобилко»:
В середине страницы находится красивый тизер продукта, у которого изображение должно принимать «неправильную» форму (в данном случае — коробка компакт-диска с загнутым углом). Так как фон не однородный (и тоже, кстати, меняется), единственным очевидным способом решения этой задачи было создание отдельного PNG-изображения весом более 100 КБ для каждого такого продукта. Меня такой расклад не устраивал, поэтому я решил в качестве эксперимента применить ictinus (на тот момент был в состоянии очень сырой альфа-версии). На прямоугольное JPEG-изображение накладывается векторная маска (в зависимости от типа продукта), затем под эту картинку ставится PNG-тень. Результат оказался более чем убедительным. Помимо сильной экономии на траффике пользователя я сэкономил нервы заказчику: теперь ему достаточно любому продукту в админке поставить галочку «Показывать на главной», а не готовить в фотошопе новые картинки.
***
С типами спрайтов, пожалуй, всё (ничего не забыл?), в следующей части рассмотрим способы хранения данных в спрайтах и некоторые рекомендации по использованию.
Скачать JS-котроллер для спрайтовой анимации