Псевдоэлемент before для маркера списка
Дата публикации: 21.02.2010
На большинстве веб-страниц присутствуют разного рода списки: меню, перечни товаров и прочее. При создании HTML эти списки превращаются в теги <ol> и <ul> (нумерованный и маркированный списки, соответственно).
Маркированные списки применяются гораздо чаще, но их проблема в том, что браузеры отображают одни и те же маркеры неодинаково. Вот например как выглядят маркеры list-style:circle;
FireFox
Opera
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 = "–" + this.innerHTML) /* хак для ие6 и 7 */ } li:before{ content: "2013"; }
Само собой в боевых условиях вместо хаков создаем отдельный CSS, который подключаем условным комментарием.
Единственная хитрость заключается в том, что нужно знать код спецсимвола (можно посмотреть у нас в HTML справочнике). В expression спецсимволы можно писать цифровым или мнемоническим кодом, а в свойстве content ставим слеш и шестнадцатеричный код (переводим в шестнадцатеричную систему обычный числовой код).
Рисуем маркеры сами
Если маркер выглядит, например так:
то есть его можно нарисовать с помощью 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 данный фрагмент выглядит так:
<a href="/en/" title="Home">Home</a> > <a href="/en/content/Sports/" title="Olympic Sports">Olympic Sports</a> > Volleyball
Не будем вдаваться в лишние разглагольствования по поводу молодцов, которые это верстали. Лучше разберем, как это можно сделать правильнее и красивее.
Прежде всего HTML. Это обычный список. Никаких классов для li мы, конечно, не используем, так как знаем как избавиться от дополнительного класса для первого элемента.
<ul> <li><a href="#">Home</a></li> <li><a href="#">Olympic Sports</a></li> <li>Volleyball</li> </ul>
Как вставить спецсимвол перед каждым элементом списка, это мы уже знаем:
li:before{ content: "3ea0"; } li{ //z-index: expression(runtimeStyle.zIndex = 1, this.innerHTML = "> " + this.innerHTML) /* хак для ие6 и 7 */ }
Теперь остался последний штрих. Нужно вставить спецсимвол не всем подряд элементам списка, а всем кроме первого. Для этого воспользуемся мощной связкой before+first-child. Собственно для всех нормальных браузеров достаточно будет такой записи:
li:first-child:before{ content:""; }
А для особо «одаренных» (IE 6-7) придется подправить expression. В итоге CSS будет выглядеть так:
li:before{ content:"3ea0"; /* вставляем маркер-скобку в браузерах понимающих before */ } li:first-child:before{ content:""; /* для первого элемента вставку не производим*/ } li { //z-index: expression(runtimeStyle.zIndex = 1, this == parentNode.firstChild ? 0 : this.innerHTML = "> " + this.innerHTML ); /* Хак для IE6-7. После загрузки документа проверяем, является ли элемент списка первым. Если да, то ничего не делаем. Иначе добавляем макрер-скобку. */ }
Данный прием подходит как для «хлебных крошек» так и, например, для различных меню.
Демо пример. Проверено в:
Вывод
Динамическая вставка контента с помощью псевдоэлемента before позволяет избежать использования дополнительной картинки и, соответственно, несколько уменьшить нагрузку на сервер. Применение приема ограничено видом маркера и набором адекватных спецсимволов, но для списков в контентной области сайта, где оформление бывает скромным это хороший вариант.
Связка before+first-child дает возможность избавиться от лишних классов и элементов при верстке «хлебных крошек» и некоторых видов меню.