После многочисленных статей (на русском и английском) на тему использования стилей для Rollover-эффектов, уменьшения задержки при открытии страницы и нагрузки на сервер, я хочу раскритиковать использование CSS Sprites. В качестве более зрелого и мощного способа можно предложить использование data:URL
и ряд дополнительных методик. На мой взгляд, область применения CSS Sprites весьма ограничена, я хочу постараться обозначить ее данной статьей и указать, когда их лучше не использовать.
С какими проблемами сталкивается верстальщик, когда использует спрайты? Это, в первую очередь, проблемы изменения каждой конкретной картинки в общем массиве. Мало того, что нужно открыть ресурсную картинку, найти в ней область, соответствующую данному небольшому изображению (которое меняется), и заменить ее, не потеряв палитру при всех изменениях. Также при изменении расположения картинок в ресурсном файле (например, перераспределили свободное место в связи с очередными дизайнерскими изменениями) нужно заново пересчитать все координаты и внести соответствия в CSS-файл.
При небольшом количестве спрайтов или их равномерном распределении (например, для пунктов меню) это будет не очень сложно. Но если ресурсный файл представляет собой набор картинок разных размеров, например, как у Google? Тогда любое изменение может превратиться в ночной кошмар. В любом случае на использование спрайтов тратится дополнительное время при разработке сайтов. Взять хотя бы следующий пример:
Спасибо rsa, также у IE возникают проблемы с позиционированием полупрозрачных PNG-картинок (которые нужно вставлять через AlpaImageLoader
). Таким образом, больше одной такой картинки в спрайт не добавить (в левый верхний угол).Спасибо sirus, это можно обойти при помощи crop
или, как указал pepelsbey, абсолютного позиционирования и дополнительной разметки.
Казалось бы, CSS Sprites призваны уменьшить задержку при загрузке страницы, однако, на практике так происходит только при правильном подходе. Обычно в ресурсную картинку кидается все подряд, картинка многократно увеличивается, а визуальная задержка при загрузке сайта может и возрасти: пользовать может ждать 1 большую картинку дольше, чем половину входящих в нее маленьких, а последние обеспечат ему «почти» загрузку сайта.
Далее, если спрайтов у нас немного (1–2 картинки), то общее время загрузки сайта, скорее всего, возрастет. Это связано с тем, что браузер не сможет открыть, как минимум, 6–7 дополнительных соединений (к хостам, где расположена статика) и загрузить все исходные картинки параллельно, а не последовательно. При небольшой сетевой задержке это может оказать решающее воздействие.
Даже положившись на то, что спрайты поддерживаются (почти) всеми браузерами на данный момент, все равно остается достаточно много вопросов, которые они не только не решают, а скорее, сами создают. Во-первых, это проблемы при использовании иконок для списка. Как я указывал в своей статье, в таком случае необходимо располагать маленькие картинки «лесенкой», но, в общем случае, это увеличивает размер получившейся картинки на 20–30%.
Во-вторых, при использовании спрайтов, когда пытаются обойти обрисованную проблему с «выползанием» фона для ненужных элементов, в структуре страницы появляются несемантические элементы, которые, по сути, заменяют тег img
, только через фоновое изображение. Такое засорение структуры страницы вредно отражается на всех уровнях разработки и использования сайта.
В-третьих, если логотип склеен с другими картинками (как у вышеуказанного примера), то становится невозможным его использование как обычной картинки (например, в версии для печати или на внешних ресурсах).
Обрисованная картина поистине ужасна. Верстальщик балансирует между размером страницы и удобством использования, пользователь в недоумении смотрит на сайт без картинок, ибо они еще не загрузились (либо видит разноцветный фон под половиной элементов), а поисковый робот продирается сквозь кучу мусора в коде. Всем плохо.
Сразу скажу, что не предлагаю панацею. Я лишь обрисовал проблемы, которые могут быть преодолены, но нет никакой «серебряной пули». Ниже я предлагаю свой взгляд на возможное решение.
С развитием техник data:URL (в том числе, кроссбраузерное их применение) наиболее логичным выходом из сложившейся ситуации будет следующее:
Чем это хорошо? Верстальщик не думает лишний раз, что и как ему расположить и нарезать: эти операции уже включено в процесс публикации сайта, автоматизированы и максимально адаптированы под пользователей.
Чем это плохо? В общем случае, загрузка страницы не ускорится, а даже может замедлиться, потому что фоновые картинки (включенные через data:URL) будут грузиться в один поток, а не в несколько при обычном использовании спрайтов. Если фоновых картинок достаточно много (несколько десятков Кб), то это окажется существенным. При небольшом их объеме (до 10Кб) будет заметно явное ускорение.
Для случаев больших объемов вышеуказанных подход не подходит. Точнее, он был бы просто идеальным, если бы все браузеры могли загружать CSS-файлы в несколько потоков (возможно, есть решение, позволяющее максимально быстро начать множественную загрузку файлов стилей) это позволило бы разбить фоновые картинки на группы по 5–10Кб и загружать их максимально параллельно.
Разбиение CSS-файла на основной и ряд дополнительных, содержащих фоновые картинки также позволит решить проблему кеширования (CSS-объявления будут кешироваться, фактически, независимо от самих картинок, что не происходит в случае одного монолитного файла). Однако, пока мне не известен механизм, который позволял бы наиболее эффективно использовать данный подход. Загрузку нескольких CSS-файлов в один поток я не рассматриваю в качестве реальной альтернативы использованию CSS Sprites.
Под алгоритмическим кешированием я имею в виду подход, описанный в соответствующей статье: он, по сути, является логическим продолжением техники предзагрузки картинок через new Image()
, однако, оперирует данными об общем размере картинок и всей страницы. Как применение его в данном случае я могу порекомендовать нарезать CSS Sprites на 6–8 частей (не меньше 5Кб каждая, при малом объеме картинок их все же лучше включать в CSS-файл).
Например, пусть у вас есть графическое меню, пункты которого изменяются при наведении. Всего пунктов 6, каждая картинка занимает 3Кб (всего 12 картинок). Так вот, вместо создания монолитного спрайта на 36КБ я предложил бы в данном случае создать 6 спрайтов по 6Кб (на каждый пункт меню), добавить их в предзагрузку сразу в head
странице. Это упростит их возможное изменение, ускорит «визуальную» загрузку (отдельные картинки появятся быстрее), и крайне слабо отразится на общей скорости загрузки (она немного упадет, ибо нужно будет открыть по 2 соединения к 3 хостам (в идеальном случае)). В случае же повторного захода скорость прохождения 304 ответов не влияет на отображения страницы.
Я надеюсь, данная статья заставит немного задуматься всех, кто уже активно использует спрайты. Все, кто еще не знаком с этой техникой, советую относиться к ней с осторожностью: иногда можно и переборщить. Те же, кто заботится о максимальной производительности своих страниц, я надеюсь, почерпнут несколько полезных советов.
Массовое использование data:URL не за горами, но пока общая технология недостаточно обкатана, чтобы включать ее в процесс разработки веб-сайтов. Однако, это будущее уже рядом, будьте наготове :)