Статьи

Автор: Николай Мациевский aka sunnybear
Опубликована: 15 января 2008

CSS Sprites: все, что вы знали, но боялись спросить

Сейчас уже много где написано и упомянуто про технику CSS sprites (aka CSS Image Maps). Я не буду открывать Америку и рассказывать о ней дотошно еще раз, а просто хочу привести несколько примеров и полезных ссылок. И пару советов из собственной практики.

Сама техника заключается в том, что мы создаем комбинированное изображение, из которого затем «вырезаем» с помощью свойств background-position нужный нам в данном случае кусок. На текущем уровне поддержки браузерами (я полагаю, что 99,9%) оно является просто must-have для любого уважающего себя интернет-ресурса (ибо позволяет сократить число запросов к серверу, отделить поведение от представления, возложить труд по анимации на CSS-движок браузера, а не на JS-движок, т.е. это будет работать даже с выключенными скриптами, и много-много прочих «вкусностей»). Но обо всем по порядку. Поехали.

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

Простой rollover-эффект

Обычно таким термином называют смену графической картинки при наведении на нее мышки, своеобразный call-to-action. У вебмастеров сложилась дурная практика делать такие эффекты через onmouseover/onmouseout на картинках. Я не буду говорить о том, что это прямое нарушения принципа разделение представления от поведения и несемантическая (в лучшем случае, в худшем — еще и невалидная) верстка. Это просто плохо, очень плохо. Я просто дам простейший пример, когда это делается средствами CSS, и является семантически-правильным (в большинстве случаев это ссылка, но с элементами форм приходится немного повозиться, согласен). Итак, примеры:

Простая кнопка About Us. При наведении просто показывается другая картинка.

Background для ссылки

Более интересный пример с анимированный логотипом. При наведении показывается анимированная часть картинки, логотип «оживает», однако за это приходится платить размером (20 Кб).

Сложный rollover-эффект

Под таким термином я понимаю случаи, когда в одном файле содержатся нескольких «динамических кнопок». В общем, при первом взгляде на картинки все должно быть ясно.

Еще один пример с фиксированными по ширине кнопками

Фиксированные кнопки

Матрица кнопок. Опять-таки, все фиксировано.

Матрица кнопок

Еще одна матрица. На этот раз меню на Apple.com. За пример спасибо посмотреть профиль  Sabiko

Меню на apple.com

Еще один пример с фиксированными кнопками. Авторы гарантируют, что в IE не будет происходить мигание фона (при наведении, фактически, фоновая картинка не меняется, просто фон становится прозрачным и «просвечивает» фон родителя. Правда, я так понимаю, это требует дополнительных, возможно, несемантических элементов в верстке. В общем, на любителя, но в определенных случаях можно использовать).

CSS Image map

Я намеренно выделил этот пункт, ибо в предыдущем все области были одинаковыми, а в данном разделе размер областей может быть, вообще говоря, произвольным. Одним из хинтов является совмещение разных областей, чтобы они занимали минимум места. Эта техника как раз и заменила классический Image Map.

Классические примеры без использованию техники CSS Sprites. Заметны задержки при отображении отдельных областей на общей картинке.

Области не пересекаются. Размер картинок, показываемых при наведении, совпадает с размером исходных картинок.

Карта монитора

Области также не пересекаются, просто в отличие от предыдущего случая, они все расположены горизонтально.

Карта города

А вот тут уже области разные

Разные области

Статичные картинки

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

Набор иконок. Основной опасностью таких файлов является «наложение» фоновых картинок одного блока на фон другого. Лучше всего это видно при увеличении размера шрифта: блок становится выше или длиннее, и запаса полей данного изображения уже не хватает, в результате у одного элемента отображается сразу несколько иконок. Непорядок. Как с ним бороться, я расскажу ниже в общих советах по созданию ресурсных картинок для CSS sprites.

Иконки

Аналогичная проблема

Иконки

В этом случае авторы поступают наиболее мудро: они жестко ограничивают размеры контейнера, у которого заданы определенные фоновые картинки, поэтому даже при увеличенном тексте картинка не «ломается» (однако, текст становится нечитаемым). Как бороться с последней напастью я также расскажу в конце заметки.

Все-в-одной

Здесь я выделил пару случаев, когда авторы стараются максимально оптимизировать число загружаемых файлов и объединяют порядка десятка различных картинок в одном файле.

Комбинированный пример. Автор использует ресурсный файл как для элементов списка (и та же самая проблема), так и для фона обычных картинок (с фиксированными шириной и высотой). В последнем случае, естественно, все ок.

Мой собственный пример. Для всех «статичных» картинок — один файл. Проблем при любом масштабировании текста не наблюдается.

Онлайн-генераторы

Оговорюсь сразу, онлайн-генераторами не пользовался, предпочитаю делать все «ручками» в Photoshop'е.

www.csssprites.com. Довольно минималистичный дизайн, есть возможность загружать несколько исходных файлов.

printf.ru/spritr/. За пример спасибо посмотреть профиль printf. Есть возможность загружать несколько файлов, очень милый дизайн, но, в целом, настроек мало.

spritegen.website-performance.org. Много настроек, позволяет гибко генерить и сам CSS-фрагмент, но все картинки нужно загружать одним архивом.

Полезные советы

Итак, самое вкусное. Для начала я бы советовал разбить все фоновые картинки на 5 групп:

  1. Анимированные картинки
  2. Те, которые предполагается распространять по всем направлениям (repeat)
  3. Те, которые предполагается распространять по горизонтали (repeat-x)
  4. Те, которые предполагается распространять по вертикали (repeat-y)
  5. И те, которые предполагается показывать только один раз (no repeat)

Выделение первой группы опционально, она может быть объединена с пятой, но тут уже надо решать на конкретных случаях (да и автор сайта выше решил, что 20 Кб его посетители переживут, и не побоялся их объединить). Откуда взялось разделение на остальные группы? Из очень простых соображений: если картинка будет повторяться по какому-то направлению, то по этому направлению она должна быть она-единственная в своем «окне», иначе повторяться будет не только она одна. Также я бы порекомендовал ориентироваться на общий размер файла в 10-20 Кб, если файл получается больше, то лучше подключать больше одного.

Далее, все картинки из группы 2 оставляем, как есть (вообще говоря, можно подумать над их преобразованием в стилевые правила для самых простых случаев, но это уже тема для отдельной дискуссии на тему особых извращений). Все картинки из группы 3 можно склеить по вертикали (тогда в своем горизонтальном окне они будут единственны), все картинки из группы 4 — по горизонтали. Что же делать с группой 5?

Тут нам нужно понять, для какой цели будет использовать каждая картинка. Если она будет изображать фиксированную по размерам кнопку, то ее можно размещать в любом месте итогового ресурсного файла, если она будет использована как иконка для списка (размещение в левом верхнем углу элемента), то мы должны очистить все пространство правее и ниже ее, чтобы при любом увеличении такого элемента (а «растут» элементы у нас всегда вниз и вправо) ничего лишнего не выводилось. Как пример можно привести картинку с последнего ресурса. В таком случае в иконки располагаются не вертикально, а «лесенкой».

Описанная выше проблема с изменением размера надписей в фиксированных кнопках (фон у них фиксированный, поэтому мы не можем их раздвигать при увеличении шрифта, и он обрезается) может быть преодолена путей разбиения фона на 4 части (угловые) и задания соответствующего цвета фона для всех элементов. Однако, это повлечет наличие, как минимум, 4 вложенных элементов для отображения каждого угла. Не во всех случаях это допустимо семантически (да, можно генерить дополнительную разметку JavaScript'ом, но насколько оно того будет стоить? Лучше решать в каждом конкретном случае).

Читать дальше

Все комментарии (habrahabr.ru)