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. 31 мая 2010 г. в 09:46

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

  2. 31 мая 2010 г. в 12:36

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

    1. 31 мая 2010 г. в 15:26 / ответ на коммент SAG

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

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

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

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

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

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

  3. Alex_la
    31 мая 2010 г. в 12:46

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

  4. SEO оптимизато
    31 мая 2010 г. в 13:07

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

    1. Спасибо! ;0)

  5. Vlad
    31 мая 2010 г. в 13:59

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

    1. 31 мая 2010 г. в 15:30 / ответ на коммент Vlad

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

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

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

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

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

      1. Vlad
        3 июня 2010 г. в 22:32 / ответ на коммент Dimox

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

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

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

  6. 31 мая 2010 г. в 16:23

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

  7. 31 мая 2010 г. в 22:52

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

  8. 31 мая 2010 г. в 23:41

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

  9. Mak
    1 июня 2010 г. в 11:24

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

  10. Руслан
    2 июня 2010 г. в 10:47

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

  11. 6 июня 2010 г. в 13:17

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

  12. 29 июля 2010 г. в 20:11

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

  13. Kama
    25 августа 2010 г. в 18:34

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

    1. 25 августа 2010 г. в 19:26 / ответ на коммент Kama

      Пожалуйста! И тебе очередное спасибо за приятный комментарий ;0)

  14. pash
    8 сентября 2010 г. в 12:13

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

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

    1. 8 сентября 2010 г. в 13:07 / ответ на коммент pash

      Нельзя так сделать, потому что IE вплоть до 8-й версии не поддерживает :last-child.

      1. pash
        8 сентября 2010 г. в 13:51 / ответ на коммент Dimox

        Действительно, почему то был уверен что если поддерживает first-child то и last-child тоже, оказалось ошибался. Спасибо за информацию :)

  15. Олег
    17 сентября 2010 г. в 16:29

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

  16. ps99
    5 октября 2010 г. в 14:15

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

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

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

  17. Deymos1986
    25 декабря 2010 г. в 13:57

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

    1. 25 декабря 2010 г. в 15:20 / ответ на коммент Deymos1986

      По аналогии можно и горизонтальное сделать.

  18. Николай
    23 января 2011 г. в 18:39

    Иногда придирчивые заказчики требуют чтобы маркер тоже был ссылкой или чтобы он менялся при наведении. Я всё же придерживаюсь вариантов когда маркер является фоном ссылки. Проблему с переносом, так же как и описано, решаю с помощью 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. oske
    13 марта 2011 г. в 16:00

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

  20. 17 октября 2011 г. в 09:37

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

Ваш комментарий

Жирный текст

Ссылка

Цитата

Внутристрочный код

CSS-код

HTML-код

JavaScript-код

PHP-код