FreeArtists.ruFreeartists статьи и рецензии о технологиях

Создание меню при помощи CSS и JavaScript

В этой статье мы рассмотрим примеры создания наиболее распространенных типов меню для web-сайтов. Для этого мы будем использовать семантику HTML и возможности CSS и JavaScript (DHTML).

Простое горизонтальное меню

Описание

Это простое горизонтальное меню, с очень коротким и простым кодом.

Возможности

Простая, удобная и красивая навигация на сайте с небольшим количеством разделов.

Принцип работы

Берем маркированный список со ссылками, выстраиваем его в линию и делаем выделение той ссылки, на которую наводят курсор.

Код с комментариями

1. Для начала создадим маркированный список со ссылками внутри:

<ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Works</a></li>
    <li><a href="#">Links</a></li>
    <li><a href="#">Contacts</a></li>
</ul>

2. Теперь нам надо выстроить его в линию и заодно убрать маркер, для этого напишем следующие стили:

ul li{
	list-style-type:none;
	display:inline
	}

3. Поскольку мы не можем использовать блочные свойства стилей для inline элементов, сделаем из тега a блочный элемент, а чтобы они выстроились в одну строку, добавим свойство float:left:

li a{
	display:block;
	float:left
	}

4. Вот собственно и все, осталось навести красоту.

4.1 описываем стили для текста ссылок:

li  a{
	font-family:Tahoma,Helvetica,sans-serif;
	text-decoration:none;
	color:#fff
	}

4.2 добавляем внутренние отступы и фон для ссылки:

li a{
	display:block;
	float:left;
	padding:4px 10px;
	background:#193D6A
	}

4.3 описываем псевдокласс hover:

li a:hover{
	background:#408BE8;
	padding:7px 14px;
	position:relative;
	top:-3px
	}

смотрим, что получилось

Кроссбраузерность

IE 5+; Opera 7+; FF 1+; Mozilla 1+.

Что надо иметь ввиду

Не забудьте следующему блочному элементу после меню прописать в стилях свойство clear:both, чтобы прекратить обтекание.

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

Вертикальное выпадающее меню

Описание

Это вертикальное выпадающее меню, которое позволяет разместить большое количество ссылок на ограниченной площади. Идею этого меню я позаимствовал у господина Nick Rigby, доработав меню для своих целей.

Возможности

Простая, удобная и красивая навигация на сайте с большим количеством разделов.

Принцип работы

Идея этого меню проста, как и все гениальное, и основана на псевдоклассах CSS. Используя псевдокласс hover, мы меняем свойство выпадающего блока с display:none на display:block. Т. е., при наведении мышки невидимый контейнер со ссылками становится видимым.

Код с комментариями

1. Создадим тело нашего меню:

<div id="menu_body">
   <ul id="ul1">
          <li><a href="#">menu 1</a>
                <ul>
                    <li><a href="#">sub menu 1</a></li>
                    <li><a href="#">sub menu 2</a></li>
                    <li><a href="#">sub menu 3</a></li>
                    <li><a href="#">sub menu 4</a></li>
                </ul>
         </li>

.........

   </ul>
</div>

Где <div id="menu_body"> используется для задания фона, <ul id="ul1"> — список с пунктами меню, а <li><a href="#">sub menu 1</a></li> — пункты подменю.

2. При помощи стилей уберем подменю:

#menu_body li ul{display:none}

3. Используя псевдокласс hover, сделаем подменю видимым при наведении мыши:

#menu_body li:hover ul, #menu_body li.over ul{
	display: block
	}

4. Поскольку Internet Explorer считает, что псевдоклассом hover обладает только тег a, добавим небольшой код на JavaScript, который это исправит:

startList = function() {
     if (document.all&&document.getElementById) {
         navRoot = document.getElementById("ul1");
         for (i=0; i<navRoot.childNodes.length; i++) {
              node = navRoot.childNodes[i];
              if (node.nodeName=="LI") {
                  node.onmouseover=function() {
                      this.className+=" over";
                  }
               node.onmouseout=function() {
               this.className=this.className.replace(" over","");
                  }
              }
         }
     }
}
window.onload=startList;

5. Вот собственно и все, осталось навести красоту:

#menu_body{
	background:#81A192;
	width:200px
	}
	
#menu_body ul li{
	list-style-type:none;
	border-bottom:1px solid #fff;
	margin-left:-40px;
	padding-left:7px
	}

#menu_body ul li a{
	color:#fff;
	font-family:verdana,arial,sans-serif;
	text-decoration:none
	}
	
#menu_body ul li ul li{
	border:0;
	list-style-type:square;
	color:#fff;
	list-style-position:inside
	}
	
#menu_body ul li ul{
	border-top:1px solid #fff;
	margin-left:-7px;
	padding-left:50px
	}

смотрим, что получилось

Кроссбраузерность

IE 5+; Opera 7+; FF 1+; Mozilla 1+.

Что надо иметь в виду

У этого меню есть два очень серьезных недостатка: если список разделов или подразделов очень велик, то при открытии подменю появляется полоса прокрутки, а когда вы хотите прокрутить страницу, меню закрывается; если у пользователя старого браузера не работает это меню, то он вообще не сможет перемещаться по вашему сайту.

Вертикальное раскрывающееся меню

Описание

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

Возможности

Простая, удобная и красивая навигация на сайте с большим количеством разделов, которая будет работать во всех браузерах.

Принцип работы

Используя, как и в предыдущем примере, вложенные списки и свойства CSS display, добавляем короткий код на JavaScript для управления видимостью раскрывающихся блоков.

Код с комментариями

1. Создадим тело нашего меню:

<ul id="menu">
  <li><a href="#" onclick="openMenu(this);return false">menu 1</a>
    <ul>
      <li><a href="#">sub menu 1</a></li>
      <li><a href="#">sub menu 2</a></li>
      <li><a href="#">sub menu 3</a></li>
      <li><a href="#">sub menu 4</a></li>
      <li><a href="#">sub menu 5</a></li>
      <li><a href="#">sub menu 6</a></li>
      <li><a href="#">sub menu 7</a></li>
   </ul>
 </li>

.........

</ul>

Где <div id="menu"> используется для задания фона, <li><a href="#" onclick = "openMenu(this);return false">menu 1</a> — пункты меню c вызовом функции открытия или закрытия подменю по событию onclick.

2. Напишем функцию на JavaScript, которая будет открывать и закрывать подменю.

function openMenu(node){
	var subMenu = node.parentNode.getElementsByTagName("ul")[0];
	subMenu.style.display == "none" ? subMenu.style.display = "block" : subMenu.style.display = "none";
}

3. Позаботимся о пользователях старых браузеров, и вместо того, чтобы писать в стилях #menu li ul{display:none}, напишем еще одну функцию, которая будет закрывать все подменю при загрузке страницы. Если по каким-либо причинам наш JavaScript код не сработает, меню будет полностью открыто и позволит пользователю кликать на ссылки подменю.

function allClose(){
	var list = document.getElementById("menu").getElementsByTagName("ul");
	for(var i=0;i<list.length;i++){
		list[i].style.display = "none";
	}
}

4. Поставим вызов этой функции на загрузку страницы.

<body onload="allClose()">

5. Вот собственно и все, осталось навести красоту:

#menu{background:#81A192;width:200px;list-style-type:none;padding:0;margin:0}
#menu li{border-bottom:1px solid #fff;padding:3px}
#menu li a{color:#fff;font-family:verdana,arial,sans-serif;text-decoration:none}
#menu li ul{border-top:1px solid #fff;padding:0;margin:0;list-style-type:square;list-style-position:inside}
#menu li ul li{border:0;list-style-type:square;color:#fff;list-style-position:inside}

Кроссбраузерность

IE 5+; Opera 7+; FF 1+; Mozilla 1+.

смотрим, что получилось

P.S.

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

62 комментария

  1. Теплов

    Пока сайт не загрузится полностью, со всеми картинками, менюха открывается полностью, со всеми вложениями. Можно ли этого избежать?

    19 ноября 2008, 19:29
  2. admin

    Можно, напишите для соответствующих тегов LI правило display:none.

    19 ноября 2008, 19:52
  3. Dave

    Спасибо за статью! А есть подобный вариант для горизонтального меню?

    23 ноября 2008, 16:34
  4. Ян

    Большое спасибо за статью, отличная менюшка!

    Подскажите пожалуйста, можно как-нибудь сделать чтобы при нажатии на ссылку
    menu 1 открывалось не только подменю, но и одновременно заданная страница.

    2 декабря 2008, 20:49
  5. Павел

    Первое меню — отстой. При увеличение пунктов меню само меню не должно менять размеры.

    3 декабря 2008, 13:33
  6. UdarEC

    Спасиб, помог очень!

    12 декабря 2008, 23:12
  7. Алексей

    Спасибо! Хорошый сайт! :)

    16 января 2009, 14:18
  8. Аноним

    а как быть если я хочу сделать меню №2,3 но я хочу чтобы у слов menu 1… были свои стили, свой фон, а суб уже имел свои стили…??

    27 января 2009, 22:22
  9. Свят

    А как быть если я хочу словам menu 1 придать свои стили, свои фоны..?

    27 января 2009, 22:24
  10. Свят

    словам меню 1 меню 2 … я про эти, а чтобы у вложенных были свои стили, такое возможно?

    27 января 2009, 22:26
  11. Sq.Piglet

    Все возможно, меняйте оформление через CSS.

    27 января 2009, 23:56
  12. Свят

    А можноли сделать так чтобы все меню сразу не открывались(3 вариант меню), т.е. если отрыто первое меню и переключался пользователь на второе то первое закрывалосьбы
    ??

    2 февраля 2009, 16:09
  13. Вадим

    Очь клевая статья, спасибо, вроде б помогло. Но есть одно но!.. Я сделал второй вариант менюшки в html-таблицах и выходит так, что код открывает лишь первую менюшку, все остальные получились нерабочими. Код javascript повставлял на все странички даже, все-равно не работает ((
    сайт hacking.net.ua, помогите плз.

    9 марта 2009, 17:19
  14. aclahoma

    нет слов…

    24 марта 2009, 10:33
  15. RSA

    Ян писал
    Подскажите пожалуйста, можно как-нибудь сделать чтобы при нажатии на ссылку
    menu 1 открывалось не только подменю, но и одновременно заданная страница.

    Свят писал
    А можно ли сделать так чтобы все меню сразу не открывались(3 вариант меню), т.е. если отрыто первое меню и переключался пользователь на второе то первое закрывалось бы ??

    ОЧЕНЬ АКТУАЛЬНЫЕ ВОПРОСЫ
    если можете подскажите как это реализовать или где об этом можно почитать.

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

    12 апреля 2009, 12:35
  16. Sq.Piglet

    Это не правильный подход, такое поведение меню надо программировать на стороне сервера, а не на JavaScript.

    13 апреля 2009, 10:25
  17. lita

    Спасибо, очень пригодились рекомендации

    27 мая 2009, 21:57
  18. Roman

    Супер, ща попробуем

    2 июня 2009, 17:54
  19. ResNullius

    Очень полезная статья! Большое спасибо автору! На основе его меню удалось выстроить неплохой (во всяком случае, я так думаю ;-) ) каталог продукции (пришлось, правда, дописать еще одну функцию на JS и в полной мере использовать PHP). Но авторские идея и изложение очень помогли!

    4 августа 2009, 14:45
  20. seacon

    Хорошая статья, а как расположить это горизонтально расположенное меню, по середине страницы?

    11 августа 2009, 16:59
  21. Андрей

    Спасибо! Отличная статья! Очень помог мне код второго меню. Именно то что искал, за одним исключением: не могу никак сделать, чтобы функция схлопывающая все меню при загрузке страницы оставляла открытым активное подменю. Может кто подскажет как это реализовать? Спасибо!

    12 августа 2009, 15:50
  22. Вячеслав

    Андрей, чтобы активное подменю оставалось открытым, необходимо писать соответстующий код на стороне сервера, например, на PHP. Посмотреть как это работает можно на моем сайте: http://www.e-pitanie.ru/. Если заинтересуешься, то могу выслать фрагмент кода.
    А автору большое спасибо за статью.

    19 августа 2009, 19:56
  23. Маршал

    Отличный скрипт!!!!!! (Я про вертикальное раскрывающееся меню). Мне очень помог!!!
    Но есть два вопроса.
    Первое. Как сделать, чтобы подпункты ракрывались плавно, с эдакой анимацией?
    Второе. Как сделать сохранение информации о закрытых и открытых пунктах в cookie, чтобы в случае перехода на другую страницу иди при презагрузке страницы открытые пункты оставалисть открытыми, а закрытые — закрытыми.

    Заранее спасибо.

    22 августа 2009, 23:37
  24. JAH

    я пишу на пхп (к сожалению мало еще мало опыта)

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

    спасибо заранее

    если кто может помочь напишите плз

    jah_ss@i.ua

    21 сентября 2009, 11:23
  25. Роман

    круто ребя! молодцы)

    28 октября 2009, 17:41
  26. Антон

    Большое спасибо!!!

    2 ноября 2009, 0:29
  27. Дарья

    Сделала меню, все замечательно, но JavaScript в explorer не работает, что делать?

    5 ноября 2009, 16:48
  28. Sq.Piglet

    Отлаживать JS. Проверил примеры на сайте, все работает.

    5 ноября 2009, 17:06
  29. CP

    в примере интересный эффект происходит когда js отключаешь)

    1 февраля 2010, 1:04
  30. Жанна

    Объясните, пожалуйста, где всё это нужно прописывать и куда прикручивать JavaScript? Ничего не понимаю…:(( Я тоже хочу красивую менюшку!

    3 февраля 2010, 1:22
  31. Сергей

    Подскажите как делается что при переходе по ссылкам меню на другие страницы меню остается на месте то есть что при создании новой страницы нужно опять добавлять эти строки меню и стиль?

    4 февраля 2010, 21:28
  32. Алексей

    Отличная статья, все работает. Только может кто-то подскажет как добавить еще один уровень вложенности меню ?

    23 апреля 2010, 17:12
  33. Вера

    Не работает в EI6 помогите чайнику(((

    7 мая 2010, 19:37
  34. Bogir

    Спасибо автору!

    13 июня 2010, 1:51
  35. добрый

    добрый вечер…как дополнить код, что бы когда одно меню с подменю открыто, при открытие нового, старое закрывалось…спасибо.

    27 декабря 2010, 20:51
  36. Юра

    Спасибо, очень помогло)

    12 января 2011, 0:37
  37. footbal

    Спасибо, долго искал его

    2 февраля 2011, 20:49
  38. Алексей

    в дизайне сайте предполагает две таких вертикальных раскрывающихся менюшки, но когда я сделал вторую меню, то увидел что функция Close распростанилась только на первое меню, второе осталось полностью открытым. Как сделать чтоб все подобного вида менюшки были закрытыми при загрузке?

    3 февраля 2011, 12:03
  39. Макси

    Спасибо за статью, хорошая!!!
    Не подскажите, как присвоить к ссылкам меню изображение, плавающее, чтобы сделать меню красивее?

    25 февраля 2011, 13:55
  40. Nik Shinkareff

    Макси:
    попробуйте задать в CSS для li или ul параметр background: url(/image.jpg);

    А вот у меня такой вопрос:
    что если наш список имеет не один уровень вложения, а 3 и более? А при развороте категории у меня разворачивается полностью дерево всех ее вложений. Баг или код требует доработки?

    14 мая 2011, 17:05
  41. Sq.Piglet

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

    14 мая 2011, 22:42
  42. Zerber

    Простенько и без затей. Отлично. Кому нужны затеи — дописывайте..

    26 августа 2011, 15:22
  43. Волк

    Зачётная статья, если не хочется рад менюхи библиотеку функций тащить. Новичку само то!

    7 сентября 2011, 17:32
  44. FlowerBoy

    Спасибо за териториал! Очень помогло. Если б еще показали горизонтальное меню) было б еще лучше!

    21 сентября 2011, 22:50
  45. Aslan

    СПАСИБО!!!!

    5 октября 2011, 22:33
  46. Фарад

    Спасибо, но как в 3 вариант доработать.

    Чтобы только одно подменю оставалось окрытым, а другие закрывались.

    15 октября 2011, 0:51
  47. Александр

    Скажите пожалуйста, как в третьем меню, вместо id=menu сделать class=menu, если просто меняешь, не работает, нужно что то в js менять… Очень нужно, помогите пожалуйста

    11 декабря 2011, 20:33
  48. Sq.Piglet

    Нужно изменить document.getElementById(«menu») на конструкцию выбирающую класс. На данный момент статья устарела, подобный фокусы сейчас делают, используя jQuery.

    11 декабря 2011, 20:50
  49. Александр

    Я не силен в js и не знаю какую конструкцию вставить :-) А на jQuery тем более, мне нужно что бы подменю открывалось не плавно, а сразу, перекопал полинтернета…
    Пробовал document.getElementByClassName(“menu”) не работает, если не трудно подскажите что вставить… или вариант на jQuery похожий есть может быть, готов заплатить, моя почта galaydas@mail.ru

    11 декабря 2011, 20:58
  50. Аноним

    А у меня вертикальное раскрывающееся меню в редакторе работает, а в браузерах не работает :(((, почему бы это?

    14 декабря 2011, 19:48
  51. Helen

    Огромное спасибо за статью.Я очень долго искала такое толковое объяснение.У меня все получилось.
    СПАСИБО еще раз

    4 февраля 2012, 19:28
  52. Валик

    Автору СПАСИБО. Безмерно благодарен, так и продолжай))) Очень доходчиво и максимально просто объяснил. Еще раз спасибо.

    9 октября 2012, 13:05
  53. Антон

    Я ни разу не писал JavaScript и тем более не знаю куда его вставлять. Просьба подробно рассказать куда что вставить. Делаю сайты на UCOZ/ Заранее спс

    12 ноября 2012, 13:13
  54. сергей

    Здравствуйте! Очень интересно! Я новичок и делаю первый сайт на WordPress. Подскажите пожалуйста, как и Антону, куда вставляется код вертикального меню

    11 декабря 2012, 19:47
  55. Вячеслав

    Как сделать так чтобы меню разбивалось еще на понпункт т.е с такой конструкцией

    вкладка|
    |_подпункт 1
    |_подпункт 2|
    |_подпнкт подпункта 1

    3 февраля 2013, 23:12
  56. Сергей

    Меню при щелчке хорошие,но в виде такой конструкции я его не применю в WordPress. Меню там сгенерируется автоматически и я не смогу ссылке поставить onclick.
    Какие еще способы есть, чтобы меню открывалось по ссылке?

    12 ноября 2013, 16:44
  57. Елена

    Спасибо очень большое!

    24 февраля 2015, 15:17
  58. Анастасия

    Все отлично, единственное что не поняла, что такое «.over» в той части кода, где мы прописываем псевдокласс для li:

    #menu_body li:hover ul, #menu_body li.over ul {
    display: block;
    }
    Объясните, пожалуйста, что такое li.over, что оно делает?

    31 августа 2015, 17:38
  59. Sq.Piglet

    Этой статье 10 лет. Лучше поискать более свежий материал.

    1 сентября 2015, 8:39
  60. Алексей

    Sq.Piglet ваш совет для изложенных ниже последствий ?

    Что-бы на старых браузерах (30% пользователей во всём мире)нечего не работало и потенциальный клиент больше никогда не вернулся на твой супер новый сайт.

    28 декабря 2015, 5:45
  61. Miniraptor

    У вас большая проблема с якорями, если поставлена ссылка в атрибут «href» у элемента то ваш код просто напросто переведет пользователя по заданной ссылке. Для исправления данного бага, необходимо прописать onclick=»javascript:void(0)», либо в самом скрипте прописать поиск элемента и поставить preventEvent у этого элемента.

    Повторюсь еще раз, работает только для якорей (элементов , где не прописан атрибут href)

    8 января 2016, 7:47
  62. Илья

    кросбраузерность это конечно круто, но сейчас немного другие требования и запросы. Такую же выпадашку можно сделать на CSS3 и она не будет работать только в ИЕ 6, остальные браузеры норм. Из подходящих примеров, например вот http://help-wp.ru/vertikalnoe-vypadayushhee-menu/

    9 февраля 2016, 12:47

RSS комментариев