Разделители в меню

5 November, 2006

XHTML/CSS

Довольно часто на практике встречаются меню с разделителями – например:
Меню с разделителями
О том как сделать такое меню с минимумом правильного HTML кода и пойдет дальше речь.

HTML

Очевидным HTML для подобных конструкций служит ненумерованный список UL, вот например такой:

  1. <ul id="nav">
  2. <li><a href="#">Главная</a></li>
  3. <li><a href="#">Новости</a></li>
  4. <li><a href="#">Каталог</a></li>
  5. <li><a href="#">Рейтинг</a></li>
  6. </ul>

Конечно если бы мы тупо и цинично рубили бабло © мы могли бы написать что то вроде:

  1. <a href="#">Главная</a> | <a href="#">Новости</a> | <a href="#">Каталог</a> | <a href="#">Рейтинг</a>

Но по причине совсем не циничной рубки (© Flack), а так же истокам проблемы с этим меню, и вдобавок семантики кода так лучше не поступать.

Как обычно делалось

Обычно для получения результата – то есть меню с вертикальными разделителями, приходилось задавать левую (или правую) границу для каждого элемента(здесь я опускаю код позиционирующий меню, он есть в примерах):

  1. #nav li{border-left:1px solid #000}

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

  1. <ul id="nav">
  2. <li class="first"><a href="#">Главная</a></li>

И потом добавлением правила:

  1. #nav li.first{border:none}

И все вроде бы работает как надо. Но. Оба эти подхода(с class=”first” и с текстовыми разделителями “|”) требуют от нас несимметричной генерации элементов – надо различать первый и все остальные LI.

Проблема(лень)

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

Решение

Идея простая как 5 копеек. Вот весь код:

  1. #nav{
  2. overflow:hidden;/* что бы UL растянулся до содержимых float во всех броузерах кроме ИЕ, а так же для нашего “обрезания”*/
  3. width:100%;/* что бы UL растянулся до содержимого в ИЕ, к самому трюку имеет косвенное отношение*/
  4. }
  5. #nav li{
  6. margin-left:-1px;/*сдвигаем все элементы влево*/
  7. }

Суть такова. Задаем overflow:hidden для UL – таким образом все что выходит за пределы блока UL отображаться не будет. Затем задаем margin-left:-1px для всех элементов списка, то есть первый элемент выйдет на 1 пиксель за пределы элемента UL, но это как раз и будет тот лишний злополучный первый разделитель! Все же остальные разделители останутся в деле – так как не выйдут за пределы блока. А первый будет скрыт. В результате получим:
Меню с разделителями
Смотреть пример

Идея

Эта же идея только с заменой на border-top и margin-top:-1px сработает и для таких меню:
Меню с горизонтальными разделителями
Смотреть пример
Более того такой прием можно применять и для графических разделителей. Будь они даже потолще одного пиксела – просто придётся задавать больший отрицателый отступ для элементов списка. Таким образом это работает и для разделителей в виде картинки.

В конце

Хотя прием и довольно узкоприменимый, но мне сэкономил время, да и идея мне понравилась. Тестировалось и работает во всех моих виндошных браузерах(IE5-7, FF, Opera). Думаю работает везде.

Буду рад услышать Ваше мнение или приемы которые вы используете!

XHTML/CSS

61 комментариев к “Разделители в меню”

Flack | 1. 5 November, 2006

Твоя обнаглел совсем :))

akella | 2. 5 November, 2006

Извини, ты прав ) я забыл © добавить

Flack | 3. 5 November, 2006

Строго говоря:
а). я так не делаю :)
б). если пунктов мало, то действительно лучше сделать через «|», особенно когда речь идет о вторичной информации (см. футер старого browsing.ru).
в). без стилей смотрится ничуть не хуже :)

akella | 4. 5 November, 2006

Я все же неправильно расставил ударения. Суть не в том что б делать не “цинично”, а в том что реализация циничного варианта в данном случае не легче чем class=”first”. В движке я имею ввиду.
Если делать списком как я говорю – все элементы получатся симметричными-одинаковыми. А в “циничном” варианте все равно надо будет различать где первый и последний в движке, что бы по краям не стояли |…

Да и что б было понятно откуда ноги – http://horo.ukr.net/ (внизу страницы). Но для маленьких, вторичных и не генерируемых из движка – согласен полностью.

Mkdir | 5. 5 November, 2006

“Конечно если бы мы тупо и цинично рубили бабло мы могли бы написать что то вроде…” ))))))))

Классная статья! То, что я давно искал!
Спасибо.

tapazukk | 6. 5 November, 2006

Браво! Публика в восхищении!
Особенно по радовало,что можно работать с бэгграундами,а еще интересно float:left вместо привычного display:inline, хотя,трюк работает и с display-inline,вот только возможность поиграться с бордерами пропадает.Еще раз-публика в восхищении :)

tapazukk | 7. 5 November, 2006

upd:поиграться не с бордерами,а с паддингами вверху и внизу

Игорь | 8. 5 November, 2006

Оригинально! Давно боролся с этим! Теперь буду умнее :))

Zigzag | 9. 6 November, 2006

хм, интересный подход, но вот если мне нужно сделать разделители меньше чем высота блока, то этот вариант не пройдет =\

akella | 10. 6 November, 2006

1) высота блока в данном случае расплывчатое понятие – задавай padding-top меньше и будет меньше высота. Но если ты имел ввиду высоту шрифта то 2)
2) используй фоновую картинку – если она будет шириной в один пиксель – то подход полностью катит. Больше пикселей? больше margin-left:-X

Вроде бы ответил?

IDcontent | 11. 6 November, 2006

Ай маладэээц, теперь я знаю как мне быстро “умирающие в градиенте” бордеры сделать для нового меню и не париться, сэнкс.

Michael Yakovis | 12. 6 November, 2006

Да, присоединяюсь к Zigzag — обычно хочется границы совсем не высоты бордера, а меньше и аккуратнее. Но способ этот я пробовал когда-то.

Александр Шабуневич | 13. 6 November, 2006

Спасибо за способ. Я сам сталкивался с этой проблемой не раз, но всегда правил для этого HTML. Теперь будем знать.

StraNNicK | 14. 7 November, 2006

Почти оффтопик: не “прийдётся”, а “придётся”. :)

Mourner | 15. 7 November, 2006

Так всегда и делаю, мне этот трюк казался очевидным. :)

akella | 16. 7 November, 2006

2Mourner: Да, спору нет, это просто – но мне нравится какая то изящность что ли, этой идеи. Что то в этом есть. И как видишь не все знали. Я за обмен опытом ;)

2Michael Yakovis: Для маленьких артинок придётся оперировать не границами а фоновыми картинками – но техника вроде бы особо не опирается именно на границы. Просто заменяем border-left на background:…. 0 50%. И дело в шляпе.

2Странник: Спасибо! Действительно провинился! Поправил.

Vadim | 17. 9 November, 2006

Действительно абсолютно прозрачный метод, в таком применении почему то не додумывался, хотя иногда могло бы стать легче, спасибо.
И теперь в подтверждение всему выше сказанному предлагаю переделать меню, находящееся внизу блога на “не для тупого рубежа бабла div#footer > p > a”, а листингами ;)

akella | 18. 9 November, 2006

Все думал кто же первый уличит :)

У меня просто фобия какая то развилась – уже год не менял ни CSS ни HTML на блоге. Тут только зацепись… перфекционизм тут же погубит меня :)

Просто вдобавок ко всему это как раз то маленькое-вторичное и не генерируемое из движка меню

IDcontent | 19. 9 November, 2006

Перфекцтонизм- зло.

ZeT | 20. 14 November, 2006

а вот вариант с “|” разделителями и намёком на css3:
хорошие броузеры:

#nav li {display:inline;}
#nav li:before {content:”\007C\00A0″;}
#nav li:first-child:before {content:””;}

он:

#nav li {behavior:expression(!this.before ? (previousSibling != null ? this.before = this.innerHTML = ‘| ‘ + this.innerHTML : ” ): ”);}

akella | 21. 14 November, 2006

Я бы обошелся CSS2:
#nav > li + li{border-left:1px solid #ccc}
:)
Но спасибо за интеерсный вариант для ИЕ )

MT | 22. 15 November, 2006

overflow: hidden как инструмент вёрстки — вообще полезная штука. ;-)

Правда, ты забыл о _положительном_ поле с противоположной стороны каждого элемента списка — для компенсации циклического сдвига элементов и соответствующего «наезжания» их друг на друга:

#nav LI {margin-left: -1px; margin-right: 1px; }

FataL | 23. 15 November, 2006

Идея супер! Особенно нравится “автоматическое” убирание лишних разделителей слева в случае, если ссылки не помещаются в одну строку. Этого не добиться ни какими CSS3!
5+

akella | 24. 15 November, 2006

MT: спасибо за совет! Я пренебрегал тем одним пикселом :)

Иван Сагалаев | 25. 21 November, 2006

Когда прочитал:

> как сделать такое меню с минимумом правильного HTML кода

Долго втыкал: это “правильный код, которого мало” или “минимально правильный код”?

:-)

akella | 26. 21 November, 2006

наверно надо было писануть:
“с минимумом максимально правильного”
:-)

tobto | 27. 24 November, 2006

полезная идея!

CooperTV | 28. 20 December, 2006

Интересно

alex | 29. 5 January, 2007

каким образом горизонтальное меню выравнять по правому краю? :/

akella | 30. 6 January, 2007

float:right для LI
или
display:inline для LI
и text-align:right для UL
или
float:left для LI
и float:right для UL

Серёга | 31. 27 January, 2007

ага!!! лень это проблема всех проблем!!!

Jurij Burkanov | 32. 8 February, 2007

Клево, спасибо!

Vladson | 33. 10 February, 2007

Ув. Серёга лень это двигатель прогресса, если бы люди в силу лени не старались всячески упростить свой труд любыми путями прогресс стоял бы на месте… :)

Q-Zma | 34. 22 March, 2007

есть несколько более сложный метод :)
http://q-zma.rajaka.net/2006/11/24/css3-selektory-first-child-i-last-child/

Ззаработок в Интернет | 35. 23 March, 2007

Да, довольно неплохое меню. Но очень часто приходится делать горизонтальное меню с выпадающим списком, а вот именно с ним и возникают проблемы. Валидности достичь можна, а вот адекватной работы во всех броузерах – практически нет. Приходится выбирать одно из двух – или валидность или нормальную работу. Я лично выбираю второй вариант.

ogonkov | 36. 31 May, 2007

а слово “лень” – это не акроним :P

а вобще очень интересно, до этого всегда использовал присваивание класса к первому пункту)

ScoDi | 37. 8 June, 2007

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

Евгений | 38. 22 August, 2007

А как это меню выровнять по центру страницы для всех браузеров?
В частности для IE6?

Для FF, Opera’ы и Safari я сделал так:

ul {
display: table;
margin: 0 auto;
}

li {
display: inline;
margin: 0 1px 0 -1px;
}

IE стал показывать у первого пункта меню разделитель :(

mihdan | 39. 16 September, 2008

Решение весьма элегантное
Код семантически верный

Спасибо-часто использую этот вариант

mihdan | 40. 16 September, 2008

2Евгений

http://css-tricks.com/examples/CenterHorizontalListItems/

оля | 41. 7 November, 2008

Отлично!!! Давно хотела узнать как это делается без first и last для li.

Автору Респект!

Bonch | 42. 14 November, 2008

Это все хорошо. Но как быть, если разделители должны быть графические? Думал-думал как сделать и пока только с ужасным нарушением семантики кое-что придумал).

Bonch | 43. 14 November, 2008

Тьфу, извиняюсь, невнимательно прочитал.

INOZ | 44. 26 January, 2009

Поднимаю вопрос, заданый Евгением (38 комментарий): а как это меню выровнять по центру страницы для всех браузеров?

akella | 45. 26 January, 2009

Попробуйте вот этот вариант http://mauzon.com/?p=87

INOZ | 46. 29 January, 2009

Благодарю! Помогло. Выкладываю решение:

Горизонтальное меню | выровненное по центру | с вертикальными разделителями

#navBox {
float: left;
left: 50%;
position: relative;
}

#navBox ul {
position: relative;
left: -50%;
float: left;
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
}

#navBox li {
float: left;
border-left: 1px #000 solid;
margin-left: -1px;
margin-top: 1px;
padding: .3em 1em;
}

#navBox a {
color: #000;
text-decoration: none;
font-weight: bold;
}

#navBox a:hover { text-decoration:underline; }

<ul>
<li><a href="#">Главная</a></li>
<li><a href="#">Новости</a></li>
<li><a href="#">Каталог</a></li>
<li><a href="#">Рейтинг</a></li>
</u>

Я нарыл еще один способ того, как выровнять меню (список) по центу: http://kizu.ru/webdev/inline-block-solved/
Но вот замутить вертикальные разделители с помощью этого метода не получится. Во всяком случае, мне не удалось.

INOZ | 47. 29 January, 2009

Тьфу какая бяка получилась. Юра, можешь сделать, чтобы мой ХТМЛ было видно? А то получилось фиг знает что.

Quaze | 48. 17 August, 2010

I wish i had a penguin, because i cant understand any of this

matros | 49. 24 September, 2010

Ну а если я хочу сделать разделители в виде наклонной черты, а не прямой:
Главная / Новости / Каталог / Рейтинг
Тогда получается тут уже фокусы не проходят и рамки бесполезны и поля? И придется цинично рубить бабло, как замечено в начале поста.

akella | 50. 24 September, 2010

Ну смотря по ситуации, можно использовать либо :after (он заменяется для ИЕ простым expression) Либо фоновую картинку слэша, либо спан со слешом – его тоже можно будет спрятать через overflow.

Ganpati-Industries.com | 51. 10 December, 2011

полезная идея!

Сергей | 52. 22 December, 2011

А как можно сделать вот эти линии (border:1px solid gray) ПУНКТ | ПУНКТ | ПУНКТ
вот эти: | ,
Как можно их из такой ситуации сделать меньше и по центру?
если ставить например к li height:10px, то они уменьшаются, но остаются в верху .

Сергей | 53. 22 December, 2011

то есть уменьшение размера border1px в высоту и равнять по центру

Modern Separators In Lists Menu « deniscyriac | 54. 22 April, 2012

[…] Here is an another interesting approach: […]

Using Separators in Lists Menu with CSS | iDearays | BlogiDearays | Blog | 55. 30 December, 2012

[…] Here is an another interesting approach: […]

некто | 56. 9 January, 2014

полезное инфо,спасибо

Алексей | 57. 16 April, 2014

вообще можно использовать li:first-child, но для Internet Explorer это свойство поддерживается начиная с 9 версии

Алексей | 58. 16 April, 2014

вообще можно использовать li:first-child, но для Internet Explorer это свойство поддерживается начиная с 9 версии :)

akela | 59. 16 April, 2014

Все правильно, но в 2006 году актуальная версия IE была 6. =)

Vladson | 60. 18 April, 2014

Кстати чем твой блог и интересен что иногда встречаются хаки которые будут работать не только на старых браузерах, но и на новых. В этом хаке например всё работает так как стандарт описывает. А основываясь на некоторых, можно придумать и новые, но уже под современные глюки браузеров (которые к сожалению увы были есть и будут)

Vladson | 61. 18 April, 2014

Я про глюки, если чо, не про браузеры (браузеры то точно будут, и сожалеть не о чем) =)

Оставить комментарий