CSS-трюк: двойные бордюры-разделители вертикального меню

Когда при верстке требуется создать меню с разделителем, я использую замечательную технику, которую когда-то давно предложил Юрий «akella» Артюх.

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

Вертикальное меню с двойным разделителем-бордюром

Возможные способы решения задачи:

  • использовать изображение;
  • использовать только CSS.

В решении необходимо предусмотреть, что:

  • высота пункта списка может меняться, т.е. текст может быть в несколько строк;
  • часть текста может быть за пределами тега ссылки.

Проблемы при использовании изображения

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

Структура HTML-кода нашего меню максимально проста:

<ul>
	<li><a href="#">Главная</a></li>
	<li><a href="#">О компании</a></li>
	<li><a href="#">Статьи</a></li>
	<li><a href="#">Отзывы</a></li>
	<li><a href="#">Фотографии</a></li>
	<li><a href="#">Вопросы</a></li>
	<li><a href="#">Контакты</a></li>
</ul>

По идее, используя технику Юры Артюха, можно было бы разделитель сделать изображением и поставить его фоном к элементу <li>. Но дело в том, что в списке у каждого пункта еще используется изображение-маркер, и если это изображение ставить фоном тега <a>, тогда возникают следующие проблемы:

  1. Если в меню появится многострочный пункт, тогда меню станет некрасивым (не хватает одинакового отступа слева у текста в каждой строке):

    Некрасивое меню

  2. Первую проблему можно было бы решить, сделав ссылку блочный элементом (a {display:block}), однако при этом возникнет другая проблема — если после ссылки добавить текст, то он перенесется на новую строку, а этого также необходимо избежать:

    Некрасивое меню

Решение с помощью CSS

Мое решение с использованием чистого CSS позволяет избежать вышеописанных проблем.

CSS-код будет выглядеть нижеследующим образом. Основные для нашей задачи стили я прокомментирую:

ul {
	width: 150px;
	padding: 0 6px;
	background: #F2F7FD url(bg.gif) 0 100% repeat-x;
 border: 1px solid #C0D7FB;
 font-weight: bold;

	overflow: hidden; /* необходимо для того, чтобы
	спрятать верхний бордюр у первого пункта и
	нижний бордюр у последнего пункта */
}
li {
	list-style: none;
 background: url(bullet.gif) 4px 8px no-repeat;
	padding: 5px 0 8px 22px;

 border-top: 1px solid #C0D7FB; /* синяя линия */
 border-bottom: 1px solid #FFF; /* белая линия */
 margin: -1px 0 -2px; /* "нахлестываем" на предыдущий и следующий пункт,
	в результате чего и достигается нужный эффект */
	height: 1%; /* для устранения бага в IE6 и IE7 */
}

Для наглядности вы можете посмотреть на живой пример.

Вот, собственно, и все. Решение кроссбраузерное, надеюсь, кому-нибудь пригодится.

* * *

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

Комментарии (28)
  1. 1

    Отличное решение! Менюшка получается очень красивой.

  2. 2
    SEO оптимизато

    Однозначно пост в закладки. Не обходиться верстка не одного сайта без заглядывание на твой сайт за полезной инфой.

  3. 4

    «Море решение с использованием чистого CSS » — опечаточка по Фрейду :) Пора в отпуск )))
    Попробуй сипользовать display:inline-block, тогда переносов не будет. + для списка можно было попробовать list-style-image.
    Так тож ниче, но придется возиться с первым или последним элементом, если вокруг списка не будет бордера.

    • 5

      “Море решение с использованием чистого CSS ” — опечаточка по Фрейду :) Пора в отпуск )))

      Спасибо, исправил.

      Попробуй сипользовать display:inline-block

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

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

      Не придется. Этот бордюр лишь для красоты, он ни на что не влияет.

  4. 6
    Alex_la

    Спасибо большое … техника супер!!!

  5. 7
    Vlad

    Решение хорошее, но описанная вначале проблема надумана — можно же просто дать LI фон, содержащий и бордюр, и маркер одновременно. Либо, сделать блочным, дать ему фон-буллет и паддинг слева.

    • 8

      Ничего не надумано. Все из собственного опыта.

      можно же просто дать LI фон, содержащий и бордюр, и маркер одновременно

      Нельзя т.к. высота LI может меняться.

      Либо, сделать блочным, дать ему фон-буллет и паддинг слева.

      Я на этот счет вообще-то написал в статье.

      • 9
        Vlad

        1) а что мешает меняться высоте LI? Например, задаем фон в видедвух полос сверху и иконки. Иконка сверху и остается, хоть 10 строк напиши. Другое дело ,если изменять расстояние от текста до верхнего края.. тогда полный швах :)

        2) сорри, не заметил. но тексту можно дать паддинг ;-)

        в любом случае спасибо!

  6. 10
    @

    Спасибо за хороший совет Dimox. Как же всё элементарно просто :)

  7. 11

    Прикольно… Можно так же сделать для горизонтального меню… Я давно хотел поискать нечто подобное, но так и не собрался с мыслями…

  8. 12

    Симпатичненько получается, респект!

  9. 13
    Mak

    Круто вообще! Офигенное решение!

  10. 14
    Руслан

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

  11. 15

    Тоже делал такое меню, статья помогла.

  12. 16
    @

    Интересное решение. Спасибо.

  13. 17
    Kama

    Читал статью давно, щас верстал и вспомнил трюк, оч. пригодился. Решил поблагодарить, собственно к чему плавно и перехожу: Спасибо!!!
    За что я и уважаю этот блог — просто, коротко, полезно :)

  14. 19
    pash

    Думаю правильнее будет использовать селекторы :first-child и :last-child (если вы не поклонник ИЕ6)

    li:first-child {
    border-top: none;
    }
    li:last-child {
    border-bottom: none;
    }

  15. 22
    Олег

    Большое спасибо!!!! Даже при том что я только 3-й день учу html, у меня уже вышла такая менюшка!!!)))) ВаУ!!!!!

  16. 23
    ps99

    минус:
    если необходимо будет сделать фон для li не прозрачным по всей ширине, то ваш трюк не проходит

    плюс:
    интересное решение :)

    я пользовался обрамляющим div’ом, чтобы он «съедал» первый и последний бордер

  17. 24
    Deymos1986

    Спасибо будем пробовать проверять. Недавно только начал заниматься html+css интересно будет попробовать… а горизонтально возможно их сделать?

  18. 26
    Николай
    @

    Иногда придирчивые заказчики требуют чтобы маркер тоже был ссылкой или чтобы он менялся при наведении. Я всё же придерживаюсь вариантов когда маркер является фоном ссылки. Проблему с переносом, так же как и описано, решаю с помощью display:block, с если есть ещё текст так никто не мешает заключить его в span например.

    <li><a href="#">О компании <span>некоторый текст</span></a></li>
    

    тогда можно

    span {
    display:block
    }
    li a {
    background: url(bullet.gif) 4px 8px no-repeat;
    }
    li a:hover {
    background: url(bullet2.gif) 4px 8px no-repeat;
    }
    
  19. 27
    oske

    хороший трюк
    переделал под себя и получилось офигенно

  20. 28

    Огромное спасибо за статью! Действительно проблема решается просто и красиво :), а самое главное кроссбраузерно…