Псевдоэлемент before для маркера списка

Автор: Александр Головко Дата публикации: 21.02.2010

На большинстве веб-страниц присутствуют разного рода списки: меню, перечни товаров и прочее. При создании HTML эти списки превращаются в теги <ol> и <ul> (нумерованный и маркированный списки, соответственно).

Маркированные списки применяются гораздо чаще, но их проблема в том, что браузеры отображают одни и те же маркеры неодинаково. Вот например как выглядят маркеры list-style:circle;

маркеры в FF FireFox
маркеры в Opera Opera
маркеры в ie IE 6-7

Это послужило одной из причин появления в грамотно сделанных CSS в составе сброса стилей, примерно таких записей:

		ol, ul {
			list-style: none;
		}
		
		

То есть мы сознательно отказываемся от использования стандартных маркеров (ну еще бы — ведь, у каждого браузера стандарт свой собственный!).

Маркеры-картинки

Естественно, просто отказаться мало — нужно найти какое-то решение задачи. Стандартный вариант — использование фонового рисунка. Нет ничего проще: для li задаем картинку-маркер и с помощью padding-left выставляем нужный отступ.

		ul {
			list-style: none; /* сбрасываем стандартный маркер */
		}
		li{
			background: url(картинка-с-самым-красивым-в-мире-маркером) no-repeat; /* вешаем новый красивый маркер */
			padding-left:20px; /* отступ подбираем исходя из размера картинки */
		}
		
		

Таким методом можно реализовать любую фантазию дизайнера:

маркеры-картинки

Плюс метода

Кроссбраузерность — в любом браузере маркер будет именно таким, как мы нарисовали.

Недостаток

Дополнительная картинка — лишнее обращение к серверу.

Before спешит на помощь

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

Естественно, если бы вставлять спецсимвол в <li> приходилось руками, об этой теме можно было бы забыть навсегда. Но на помощь к нам приходит псевдоэлемент before, который позволит этот процесс автоматизировать. Этот псевдоэлемент понимают почти все браузеры (ff, opera, chrome, ie8), а для ie6-7 cуществует решение с применением expression.

Вот такой несложный код обеспечит вставку спецсимвола «короткое тире»:

li{
	//z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "&ndash;" + this.innerHTML) /* хак для ие6 и 7 */
}

li:before{
	content: "\2013";
}

Само собой в боевых условиях вместо хаков создаем отдельный CSS, который подключаем условным комментарием.

Единственная хитрость заключается в том, что нужно знать код спецсимвола (можно посмотреть у нас в HTML справочнике). В expression спецсимволы можно писать цифровым или мнемоническим кодом, а в свойстве content ставим слеш и шестнадцатеричный код (переводим в шестнадцатеричную систему обычный числовой код).

Вариант с использованием insertAdjacentHTML

Update 1.06.10. Предыдущий вариант в некоторых случаях вызывает сбои в работе IE6. Более устойчивым является использование метода insertAdjacentHTML. Фрагмент CSS, для IE6-7 в этом варианте будет таким:

li{
	//z-index: expression(runtimeStyle.zIndex = 1, insertAdjacentHTML('afterBegin', '&ndash;')); /* хак для ие6 и 7 */
}

Рисуем маркеры сами

Если маркер выглядит, например так:

простенькие маркеры

то есть его можно нарисовать с помощью background-color и/или border, то тут тоже можно обойтись без картинки:

li{
	//z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "<div class='listMarkerBackColor'></div>" + this.innerHTML) /* хак для ие6 и 7 */
}

li:before,
.listMarkerBackColor{
	background-color:#539127;
	width:7px;
	height:7px;
	content:"";
	float:left;
	margin:4px 4px 0 0;
	overflow:hidden;
}
* html .listMarkerBackColor{
	margin-right:1px; /* исправляем маленткий косяк в IE6 */
}

Демо пример. Проверено в:

Комбинируем before и first-child

update 27.02.10

Как правило, на многих сайтах присутствуют «Хлебные крошки» — список, показывающий путь по сайту от его «корня» до текущей страницы. Вот как это выглядит, например на olimpic.org:

хлебные крошки на olimpic.org

К сожалению, непосредственно на olimpic.org данный фрагмент выглядит так:

<a href="/en/" title="Home">Home</a>
&nbsp;&gt;&nbsp;<a href="/en/content/Sports/" title="Olympic Sports">Olympic Sports</a>
&nbsp;&gt;&nbsp;Volleyball

Не будем вдаваться в лишние разглагольствования по поводу молодцов, которые это верстали. Лучше разберем, как это можно сделать правильнее и красивее.

Прежде всего HTML. Это обычный список. Никаких классов для li мы, конечно, не используем, так как знаем как избавиться от дополнительного класса для первого элемента.

<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Olympic Sports</a></li>
<li>Volleyball</li>
</ul>

Как вставить спецсимвол перед каждым элементом списка, это мы уже знаем:

li:before{
	content: "\3e\a0";
}

li{
	//z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "&gt; " + this.innerHTML) /* хак для ие6 и 7 */
}

Теперь остался последний штрих. Нужно вставить спецсимвол не всем подряд элементам списка, а всем кроме первого. Для этого воспользуемся мощной связкой before+first-child. Собственно для всех нормальных браузеров достаточно будет такой записи:

li:first-child:before{
	content:"";
}

А для особо «одаренных» (IE 6-7) придется подправить expression. В итоге CSS будет выглядеть так:

li:before{
	content:"\3e\a0"; /* вставляем маркер-скобку в браузерах понимающих before */
}

li:first-child:before{
	content:""; /* для первого элемента вставку не производим*/
}

li {
//z-index: expression(runtimeStyle.zIndex = 1, this == parentNode.firstChild ? 0 : this.innerHTML = "&gt; " + this.innerHTML );
/* Хак для IE6-7. После загрузки документа проверяем, является ли элемент списка первым. Если да, то ничего не делаем. Иначе добавляем макрер-скобку. */
}

Данный прием подходит как для «хлебных крошек» так и, например, для различных меню.

Демо пример. Проверено в:

Вывод

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

Связка before+first-child дает возможность избавиться от лишних классов и элементов при верстке «хлебных крошек» и некоторых видов меню.

Материал: