CSS спрайты

Автор: Анна Лысак и Татьяна Головко Дата публикации: 07.07.2011

CSS спрайты — отличный метод, позволяющий сократить количество необходимых запросов к серверу для загрузки изображений. По этому методу написано уже много книг и статей. Если у тебя на сайте много изображений (в большей степени касается логотипов, иконок, фоновых изображений, флагов и т.д.) ты можешь вместо множества мелких изображений сделать одно большое со всеми ними внутри и при помощи CSS определять, какая конкретно часть изображения в каком контейнере должна показываться.

Этот метод влияет на производительность, но в случае с мобильными технологиями, прежде чем использовать его, мы должны хорошенько подумать и проанализировать все возможные проблемы. Во-первых, для нормальной работы нужна полная поддержка CSS свойства background-position (это свойство включено в мобильные стандарты, так что это не такая уж и проблема). Второй момент — мы не будем использовать теги <img>. Вместо них будет использовать блочный элемент (<div>) или любой другой преобразованный в блочный элемент ( display: block). Это значит, что мы не можем использовать для изображения альтернативный текст и пока не загрузиться CSS файл, браузер не будет знать, сколько нужно выделить места под то или иное изображение.

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

Примеры и совместимость

Давай сделай пример кода при помощи двух методов: использование исходного блочного элемента (<div>) и использование исходного встроенного элемента (<a>), преобразованного в блочный элемент.

Оригиналом документа без CSS спрайтов является следующий список стран:

	<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
	"http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>Documento sin título</title>
			<style type="text/css">
				ul {
					list-style: circle;
				}
				ul li {
					padding: 0px;
					margin-bottom: 5px;
				}
				ul li img {
					margin: 0px 10px 0px 0px;
					vertical-align: middle;
					border: 1px solid gray;
				}
			</style>
		</head>
		<body>
			<h1>The Best Seller</h1>
			<h2>Select your nearest country</h2>
			<ul>
				<li><img src='ar.png' width='30' height='19' alt='AR' />
				<a href='ar'>Argentina</a></li>
				<li><img src='br.png' width='30' height='19' alt='BR' />
				<a href='br'>Brazil</a></li>
				<li><img src='fi.png' width='30' height='19' alt='FI' />
				<a href='fi'>Finland</a></li>
				<li><img src='jp.png' width='30' height='19' alt='JP' />
				<a href='jp'>Japan</a></li>
				<li><img src='es.png' width='30' height='19' alt='ES' />
				<a href='es'>Spain</a></li>
				<li><img src='us.png' width='30' height='19' alt='US' />
				<a href='us'>United States</a></li>
			</ul>
		</body>
	</html>
	

В предыдущем примере используется шесть изображений, которые могут быть сконвертированы в одно большое изображение (получается на пять HTTP запросов и заголовков меньше) при помощи следующего кода:

	<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
	"http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
	<html xmlns="http://www.w3.org/1999/xhtml">
		<head>
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
			<title>Documento sin título</title>
			<style type="text/css">
				ul {
					list-style: circle;
				}
				ul li {
					padding: 0px;
					margin-bottom: 5px;
				}
				ul li div {
					/* а вот и наше большое изображение */
					background:url(sprite.png);
					width: 30px;
					height: 19px;
					float: left;
					border: 1px solid gray;
					margin-right: 10px;
				}
			</style>
		</head>
		<body>
		<h1>The Best Seller</h1>
		<h2>Select your nearest country</h2>
			<ul>
				<li><div style="background-position: 0px 0px;"></div>
				<a href='ar'>Argentina</a></li>
				<li><div style="background-position: 0px −29px;"></div>
				<a href='br'>Brazil</a></li>
				<li><div style="background-position: 0px −58px;"></div>
				<a href='fi'>Finland</a></li>
				<li><div style="background-position: 0px −87px;"></div>
				<a href='jp'>Japan</a></li>
				<li><div style="background-position: 0px −116px;"></div>
				<a href='es'>Spain</a></li>
				<li><div style="background-position: 0px −145px;"></div>
				<a href='us'>United States</a></li>
			</ul>
		</body>
	</html>
	

Результат на рисунке 7.8:

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

Есть много онлайноввых CSS-генераторов, в которых ты можешь загрузить все изображения и уже через секунду получить одно большое изображение и CSS код для замены всех исходных тегов <img>. Примеры на http://spritegen.website-performance.org и на http://csssprites.com.

Теперь давай посмотрим, как применить этот же самый метод к такому изначально не блочному элементу как тег <a>. Нужно только не забыть сделать внутренний отступ, чтобы текст не налез на изображение. Код будет выглядеть так:

<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
"http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Documento sin título</title>
		<style type="text/css">
			ul {
				list-style: circle;
			}
			ul li {
				padding: 0px;
				margin-bottom: 5px;
			}
			ul li a {
				/* We define the large image to all divs that represent an image */
				background:url(sprite.png);
				/* We need to create block elements */
				display: block;
				/* We need the background to not be repeated */
				background-repeat: no-repeat;
				height: 19px;
				padding-left: 40px;
			}
		</style>
	</head>
	<body>
		<h1>The Best Seller</h1>
		<h2>Select your nearest country</h2>
		<ul>
			<li>
			<a href='ar' style='background-position: 0px 0px;'>Argentina</a></li>
			<li>
			<a href='br' style='background-position: 0px −29px;'>Brazil</a></li>
			<li>
			<a href='fi' style='background-position: 0px −58px;'>Finland</a></li>
			<li>
			<a href='jp' style='background-position: 0px −87px;'>Japan</a></li>
			<li>
			<a href='es' style='background-position: 0px −116px;'>Spain</a></li>
			<li>
			<a href='us' style='background-position: 0px −145px;'>United States</a></li>
		</ul>
	</body>
</html>
	

Для фотографий и больших файлов не рекомендуется использовать CSS-спрайты. Если у тебя на сайте изображения в формате PNG, то лучше всего иконки с похожей цветовой гаммой просто сгруппировать.

В таблице 7.14 приведена информация о совместимости CSS спрайтов с разными мобильными платформами.

Табл. 7.14. Таблица поддержки CSS спрайтов
Браузер/ Платформа Спрайты для блоков (<div>) Спрайты для ссылок (<a>)
Safari Да Да
Android browser Да Да
Symbian/S60 Да Да
Nokia Series 40 Да в 6-м выпуске,
Нет до 6-го выпуска
Да, бажит на low-end усройствах
webOS Да Да
BlackBerry Да, с версии 4.0 Да, с версии 4.0
NetFront Нет Да
Openwave (Myriad) Нет Нет
Internet Explorer Нет Да
Motorola Internet Browser Нет Нет
Opera Mobile Да Да
Opera Mini Да Да

Альтернативы CSS спрайтам

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

Карта изображений — первый метод, который приходит на ум как альтернатива CSS спрайтам. Но, не рекомендуется использовать его для устройств без сенсорной навигации, потому как в противном случае может существенно пострадать юзабилити.

Встроенные изображения

Как мы уже говорили в предыдущей главе, встроенные изображения — это отличный метод для современных браузеров. При разработке для браузеров, которые понимают этот метод, мы можем скопировать первый наш пример (исходный документ без CSS спрайтов) и определить каждое изображение в виде data:URL.

Объединение изображений

Если, как в нашем примере, изображения расположены рядом по вертикали или горизонтали, мы можем рассмотреть вариант соединения всех изображений в одно. Все очень похоже на CSS спрайты, но здесь мы делаем изображение с одноразовым использованием фона, настраивая margin и padding так, чтобы элементы были выровнены относительно разных частей изображения. На старых устройствах с ограниченной поддержкой margin и padding этот метод может не работать или показывать некорректные результаты.

Если мы будем использовать изначальный код, но позаботимся о правильном кэшировании на сервере, то последующие страницы будут загружаться быстрее, чем при использовании CSS спрайтов, потому что сократитятся затраты времени на рендеринг. Подробнее о кэшировании мы поговорим позже (Глава 10).

Бордюры блока

Если для оформления границ прямоугольной области ты хочешь использовать CSS спрайты, то для этого есть еще и альтернативный вариант в виде CSS расширений WebKit. Сейчас мы подробно разберемся с этим вопросом.

По теме

Куда дальше