Как добавить разные иконки к пунктам меню, используя только CSS
Суббота, 12 сентября 2009
![]()
Однажды была у меня такая задача, когда заказчик попросил прикрутить к каждому пункту меню свою иконку, но сами пункты меню выводились чистым HTML-списком, без использования различных class и id. А доступа к PHP-скриптам, выводящим меню у меня не было.
Так как же решить подобную задачу?
В CSS давно заложены инструменты для решения подобных задач без лишних мозговых усилий, поэтому долго придумывать ничего не пришлось.
Задачка
Итак, есть «чистое» меню и набор иконок, которые нужно к нему «прикрутить». Отмечу сразу, что дело довольно простое, потому что в меню не было фоновых подложек, «раздвижных дверей» и прочих вещей, усложнивших бы задачу.
HTML-код меню:
1 2 3 4 5 6 7 8 | <ul> <li><a href="#home">Главная</a></li> <li><a href="#aboutCompany">О компании</a></li> <li><a href="#catalogue">Каталог</a></li> <li><a href="#photogallery">Фотогалерея</a></li> <li><a href="#forPartners">Партнерам</a></li> <li><a href="#contact">Контакт</a></li> </ul> |
Теперь дело за CSS и навешиванием фона из спрайтов (фоновая картинка):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | * { margin: 0; padding: 0; } body { font: normal small/1.5em arial, verdana, sans-serif; background: #fff; color: #000; } ul { margin: 1em auto 1.5em 1em; list-style: none; } ul li { width: 250px; height: 2em; line-height: 2em; padding-left: 2em; background: url(menu_icons.gif) 0 50% no-repeat; } ul li+li { background-position: -300px 50%; } ul li+li+li { background-position: -600px 50%; } ul li+li+li+li { background-position: -900px 50%; } ul li+li+li+li+li { background-position: -1200px 50%; } ul li+li+li+li+li+li { background-position: -1500px 50%; } |
По-научному, называется все это страшными словами «селекторы сестринских элементов», но на самом деле не всё так сложно и пугающе.
C помощью селектора ul li мы задаем общий стиль всем пунктам меню, а потом просто сдвигаем фоновое изображение, чтобы подставить свою иконку для каждого пункта меню.
При этом селектором ul li+li мы устанавливаем фон для второго пункта меню (второго li), селектором ul li+li+li — для идущего за ним третьего, и так далее, пока меню не закончится.
Всё просто. По традиции — демо-пэйдж.
Работает везде, кроме IE6. Но это его проблемы, не так ли?
Пока большинством браузеров не поддерживается CSS3 multiple backgrounds (а поддерживается на сегодня только Safari 4), таким нехитрым способом можно смело разукрашивать меню хотя бы с одним «чистым» для установки фона элементом. Не важно, что это будет, li, span или a.
Какие возможности?
Например, так я мог бы повесить разные иконки к пунктам меню или списку архивов этого блога. Или назначить каждому пункту меню свой фоновый цвет или картинку. Или расположить ссылки на странице по кругу. Или... Экспериментируйте!
* * *
А в это время в соседних галактиках:
Для тех, кто еще рисует «вебдваноль» — подборка из бесплатных шрифтов. Несколько приятных фич для пугающего интерфейса Drupal'а. Продвижение сайта в Google с помощью SemRush.
* * *
* * *
Понравилась статья?
Тогда помогите мне сделать её доступной для других, или будьте в курсе событий:
- подпишитесь на обновления по RSS
- получайте новые статьи на E-mail

- добавьте в Twitter: Как добавить разные иконки к пунктам меню, используя только CSS
- добавьте статью в закладки:
* * *

WOW! That's great!
Спасибо! Просто офигенное решение.
Да, полноценный мультипл ждем-не дождемся.
самое бредовое решение, которое я когда-либо видел... слабо каждому li свой класс задать? при этом вы конкретно избавитесь от проблемы перестановки пунктов местами — в css в таком случае вообще ничего менять не придётся... иначе вам предстоит геморой где какое число поменять
нет как пример применения + между селекторами более-менее — но как пример здравого написания css — очень бредовый :)
и самое главное... в ИЕ6 будет работать без проблем :)
вот говорят ИЕ6 отстой и т.д... нет вы не подумайте — я с этим согласен... но иногда проблема совсем не в ИЕ6 :)
Да давно знал но ни когда не применял — (теперь есть хорошая подсказка).
Примерно подобное сделал себе на блоге для оформления комментариев (иконки комментаторов), но с помощью селекторов атрибутов и спрайта. Так как к Blogger gravatar не прикрутить :)
Ещё для таких уж не любителей ИЕ (в т.ч и ИЕ7, насчёт 8-го не уверен) — так вот... существует такой всевдоселектор
:nth-child()— в котором каждму потомку элемента можно задать свой класс... и тогда ваше безобразие с плюсами превращается во вполне красивый код:красота... да ИЕ не поддерживает... но существуют хаки, правда там всем элементам li придётся задавать свой собственный класс — о чём я собственно написал в первом своём комментарии
проверил только что — поддерживают все последние версии FF, Opera, Safari, Chrome
Steward, понавешивать class и id не слабо.
Вы бы для начала, перед тем, как комментировать, прочитали первый абзац. Там есть ответ на ваше замечание.
А то, что IE6 на корню убил все самые хорошие начинания в CSS2.1 (те же сестринские или селекторы атрибутов) никак его оправдывает.
Ок, вариант засчитан. Можно и так.
Steward, единственное замечу, что на IE8 в вашем случае полагаться не стоит. Не держит он псевдоклассы из CSS3.
Решение красивое, но, пока еще, не везде применимое.
Мелкомягкие только-только доросли до CSS2.1, утверждённого больше 10 лет назад :)
Извините конечно... я бы лично такого заказчика отправил на юх... — вам шашечки или ехать?
нет я согласен — ваш вариант рабочий и возможно единственный в поставленных условиях... вот только я бы сразу задумался об адекватности заказчика...
подметать плац можно и ломом... можно... только нах...я если есть метла?
C IE6 все не так безнадежно, достаточно написать одноразовый expression:
лучше расположить эту штуку в самом конце (из-за фигурных скобок), ну и скрыть это дело с помощью какого-нибудь хака, типа
* html {...}.[...] Как добавить разные иконки к пунктам меню, используя т
а зачем плюсы?
li li li {}[...] Как добавить разные иконки к пунктам меню, используя т
@utz0r, считаете, в этом случае будет работать? Я — нет.
Привет! Перешёл от Искариота и он меня не подвёл — такой клёвый блог порекомендовал :) Как мне не забыть? После редизайна обязательно отремонтирую свой активный блогролл и в обязательном порядке добавлю туда rotorweb.ru. Прошу мне напоминть, если это не произойдёт в ближайшие две недели. Желаю удачи!
@Тормоз, спасибо :)
Спасибо интересная статья, слышал про этот селектор, но в живом применении ни разу не видел )
Вопрос напросился, а почему спрайт не вертикальный, т.е. не просто все картинки одна под другой, так вы не ограничиваете себя в длине пункта меню, и картинка весит меньше ;) А разницы по сути только вместе X-координаты — Y менять.
Мне еще очень нравится решение которое использует yandex с
<i></i>вложенными в, где для i делается отрицательный маргин, и он вроде не в ссылке но кликабельный — очень удобной, я понимаю что не для вашей «зажатой по условиям» ситуации, а вообще )Ой, съелся тег
li, i естественного в него помещаются.@Чистяков Денис, отвечу на вопрос про спрайты.
Длинный и горизонтальный для того, чтобы не допустить «выползания» второй иконки для пункта меню при большом увеличении шрифта. Да и так их (иконки) выравнивать по вертикали намного проще — опять же, при увеличении шрифта, никуда не поедут (если выравнивать вертикальный спрайт по высоте пункта меню, то начнутся танцы с бубном, попробуйте).
А про длину пункта меню — я специально делал большие промежутки (прозрачные) между иконками, намного больше, чем ширина сайдбара. Причём, это почти не сказывается на размере GIF.
Если сайт резиновый, то можно еще больше увеличить расстояния, в расчете на ширину сайдбара на самых-самых широких мониторах.
Надеюсь, доступно объяснил?
Блин сказать нечего, а хочется! Спасибо за статейку! Иконки это хорошо! Нужно будет поэкспериментировать!