После публикации серии статей на тему использования, ненужности и даже автоматизации CSS Sprites, после многодневного анализа текущего положения вещей удалось собрать некоторый набор наиболее часто возникающих проблем при использовании CSS Sprites и методов их решения. Также далее рассматривается прикладной способ по автоматизации создания CSS Sprites для произвольного проекта.
CSS Sprites, на самом деле, — всего лишь расширенное использование технологии
Кроме заявленных свойств также есть еще несколько (например,
Итак, мы можем выставлять источник изображения, правило для его повторения и его начальную позицию. Вроде достаточно?
Естественно, рассматривая набор возможных эффектов при использовании фоновых изображений стоит отметить следующие:
Все описанные примеры можно более четко структурировать по следующим группам.
Глядя на эту спецификацию становится, в общем, понятно, в каком направлении двигаться для автоматизации создания CSS Sprites.
Далее речь пойдет уже об инструменте Auto Sprites, который был положен в основу разработки Web Optimizer. После описанных выше умозаключений оставались чисто технические вопросы: как все это закодировать.
Для начала нам нужно разобрать все дерево CSS-правил, потом отобрать из них относящиеся к фоновым изображениям и линейным размерам объектов, уже потом произвести над ними требуемые действия. Идеально для этой задачи подходит CSS Tidy, который был замечательно испробован, протестирован и улучшен после пары небольших ошибок.
Дальше начинается самое интересное: как нам вышеописанные группы «склеивать»? Для этого используется следующий алгоритм:
Все описанные шаги уже применены в Web Optimizer (веб-приложении для автоматизации клиентской оптимизации), одна из финальных версий алгоритма работает для инструмента Auto Sprites, а с исходным текстом можно ознакомиться в SVN.
Эту логику можно применить на любом этапе веб-разработки (как при начальном создании дизайна, так и при пост-релизной оптимизации сайта). Библиотека для автоматического создания спрайтов распространяется по лицензии MIT (как мне правильно указали на CodeCamp, она позволяет использовать продукт где угодно и как угодно, но обязательно должна присутствовать ссылка на первоисточник, даже если используется не вся библиотека, а только ее существенная часть).
Все картинки получены на реальной конфигурации известных CMS.
P.S. Новости по поводу Web Optimizer будут публиковаться теперь и на Twitter.
Обзор технологии
CSS Sprites, на самом деле, — всего лишь расширенное использование технологии
background
, заложенной еще в спецификации CSS1. Все, до чего додумалось прогрессивное человечество за эти годы — это множественный фон у элементов (как он будет совместим с концепцией CSS Sprites еще придется проверить). Основные свойства, которые мы используем для задания фонового изображения.background-image
— основная «рабочая лошадка». Именно за ней будущее в видеdata:URI
, который в конце концов победит CSS Sprites. Но произойдет это нескоро.background-repeat
— вторая не менее важная составляющая при использовании фонового изображения. Ведь задаваяno-repeat
для данного свойства, мы намеренно подчеркиваем, что допустимо использование CSS Sprites для «склейки» изображений (по умолчанию используетсяrepeat
).background-position
— «волшебная палочка» для CSS Sprites, позволяющая спрятать или показать определенные части фонового изображения.
Кроме заявленных свойств также есть еще несколько (например,
background-color
), но они к спрайтам имеют посредственное отношение.Итак, мы можем выставлять источник изображения, правило для его повторения и его начальную позицию. Вроде достаточно?
Прикладные тонкости
Естественно, рассматривая набор возможных эффектов при использовании фоновых изображений стоит отметить следующие:
- Объект, полностью заполненный фоновым изображением. Здесь основную роль играют конечные размеры объекта (конечно, если изображение не повторяется по всем осям сразу: в таком случае использовать его для CSS Sprites не представляется возможным). Довольно часто фон под объектом может меняться в зависимости от каких-либо условий (преднамеренный акцент или действия со стороны пользователями), но для логики создания CSS Sprites это несущественно. Здесь же можно выделить три подслучая, соответствующих неповторяющемуся фону и повторяющему по оси X или Y.
- Фоновое изображение заполняет не весь предоставленный ему объем (либо размеры объекта не заданы, либо заданы в относительных — em, % — единицах). Тут нам необходимо либо прикреплять повторяющееся изображение «в конец» спрайта, чтобы на той части объекта, что осталась без фонового изображения, не проявлялось никаких дефектов. Либо (в случае
no-repeat
) расположить изображения «лесенкой» (это особенно актуально в случае фона для элементов списка). Стоит отметить, что в зависимости от значенияbackground-position
CSS Sprites здесь могут быть как возможны, так и не возможны в принципе (например, в случае100% 100%
). Тут можно выделить еще несколько случаев, различающихся поbackground-position
,background-repeat
и линейными размерами блока. - Изображение является анимированным. Поскольку далее речь пойдет о применении PNG и JPEG-изображений для CSS Sprites, то анимированные изображения придется сразу выбросить из рассмотрения: поддержка анимированных PNG-изображений находится сейчас на самом зачаточном уровне в браузерах.
Все описанные примеры можно более четко структурировать по следующим группам.
background-repeat: no-repeat
,background-position: абсолютные числа
, и заданы линейные абсолютные размеры.background-repeat: no-repeat
,background-position: абсолютные числа
, линейные размеры не заданы или заданы в относительных единицах.background-repeat: repeat-x
, задана высота элемента.background-repeat: repeat-x
, высота элемента не задана.background-repeat: repeat-y
, задана ширина элемента.background-repeat: repeat-y
, ширина элемента не задана.background-repeat: no-repeat
,background-position: 100% 0
, задана высота элемента.background-repeat: no-repeat
,background-position: 0 100%
, задана ширина элемента.background-repeat: no-repeat
,background-position: 100% 0
, высота элемента не задана.background-repeat: no-repeat
,background-position: 0 100%
, ширина элемента не задана.background-repeat: repeat
.background-repeat: repeat-x
илиbackground-repeat: repeat-y
, размеры элемента указаны в относительных единицах.background-repeat: no-repeat
,background-position: в относительных единицах
.- изображение является анимированным GIF-файлом.
Глядя на эту спецификацию становится, в общем, понятно, в каком направлении двигаться для автоматизации создания CSS Sprites.
Практическое решение
Далее речь пойдет уже об инструменте Auto Sprites, который был положен в основу разработки Web Optimizer. После описанных выше умозаключений оставались чисто технические вопросы: как все это закодировать.
Для начала нам нужно разобрать все дерево CSS-правил, потом отобрать из них относящиеся к фоновым изображениям и линейным размерам объектов, уже потом произвести над ними требуемые действия. Идеально для этой задачи подходит CSS Tidy, который был замечательно испробован, протестирован и улучшен после пары небольших ошибок.
Дальше начинается самое интересное: как нам вышеописанные группы «склеивать»? Для этого используется следующий алгоритм:
repeat-x
изображения (группа 3) объединяются все вместе по вертикали. Попутно правится ширина фоновых изображений (приводится к общему знаменателю). В самое начало такого файла добавляютсяno-repeat
изображения, подходящие по ширине (группа 1). Далее в самый них файла записывается 1 изображение из группы 4 (больше 1 все равно никуда не войдет).- Производятся абсолютно аналогичные действия с
repeat-y
. - Далее изображения из группы 7 объединяются по вертикали (
0 100%
означает, что фон должен быть прижат к правому краю элемента, соответственно, весь спрайт будет «прижат» к правому своему краю). - Аналогично с группой 8 — прижимаем все к низу. Естественно, что для всех групп мы учитываем первоначальный
background-position
. - Рассчитываем позиционирование для изображений группы 1 (для этого подойдет и просто перебор отсортированных по площади изображений: готовим матрицу, в которую пытаемся «вписать» очередное изображение, если не получается, то матрицу увеличиваем).
- Строим «лесенку» из изображений второй группы. Лесенку лучше строить внизу уже созданного спрайта из предыдущего пункта: тогда легко найти минимальный размер «дырки» между двумя группами изображений, чтобы сдвинуть «лесенку» вверх (и потом, возможно влево). Конечно, поиск наиболее оптимального расположения — нетривильная задача. Но ее можно решить и в достаточно грубом приближении, которое описано выше.
- Изображение из пункта 3 прикрепляются к правому верхнему углу нашего сложного изображения (результат действия пунктов 5 и 6). Так как у каждого такого изображения задана допустимая высота и все они находятся вне «рабочей» зоны остальных
no-repeat
-изображений, то никаких рудиментов не возникнет. - Аналогичным образом поступаем с изображением из пункта 4 — его располагаем в нижнем левом углу нашего спрайта.
- На выходе мы получаем 3 спрайта со всеми возможными случаями. В среднем, размеры такоих спрайтов будет лишь незначительно превосходить (если вообще будет) аналогичные «ручные» аналоги (в том числе, за счет использования PNG). Естественно, что можно в автоматическом режиме пропустить через
pngcrush
илиjpegtran
. Стоит также предусмотреть, в каком виде будут создаваться полноцветные изображения: JPEG или PNG (последние больше по размеру, но гарантирует отсутствие потерь качества).
Все описанные шаги уже применены в Web Optimizer (веб-приложении для автоматизации клиентской оптимизации), одна из финальных версий алгоритма работает для инструмента Auto Sprites, а с исходным текстом можно ознакомиться в SVN.
Эту логику можно применить на любом этапе веб-разработки (как при начальном создании дизайна, так и при пост-релизной оптимизации сайта). Библиотека для автоматического создания спрайтов распространяется по лицензии MIT (как мне правильно указали на CodeCamp, она позволяет использовать продукт где угодно и как угодно, но обязательно должна присутствовать ссылка на первоисточник, даже если используется не вся библиотека, а только ее существенная часть).
Живые примеры
Все картинки получены на реальной конфигурации известных CMS.
P.S. Новости по поводу Web Optimizer будут публиковаться теперь и на Twitter.