Создание выпадающего меню на JavaScript

В этой статье рассмотрим, как создать выпадающее меню при наведении курсора мышки на пункт меню с использованием JavaScript. Пример такого меню можно посмотреть тут. Разберем последовательно все по порядку.
Выполним горизонтальное меню без применения таблиц, для этого будем использовать блоки div и свойство CSS - float (обтекание). Тогда пункты меню достаточно будет записать подряд в блоках div, с классом "punkt". Также заключим все меню в блок с классом "menu", и еще для наглядности все пункты меню поместим в блок с идентификатором "block_menu". То есть на данном этапе получим следующий HTML-код
Код
<html>
<head>
<style>
.punkt { float:left; }
.footer_menu { clear:both; }
</style>
</head>
<body>
<div class="menu">
<div id=" block_menu ">
<div class="punkt">О проекте</div>
<div class="punkt">Веб-дизайн</div>
<div class="punkt">JavaScript</div>
<div class="punkt">PHP</div>
<div class="punkt">Новости</div>
</div>

<div class="footer_menu"></div>
</div>

</body>
</html>

В итоге получим строчку из пунктов меню. Также мы добавили блок "footer_menu" со свойством CSS - "clear:both;", с помощью которого уберем действие свойства "float" пунктов меню на последующее содержимое странички.
Давайте условно назовем пункты выпадающего меню - подпунктами, чтобы мы не путались в дальнейшем с пунктами меню разного уровня.
Далее, мне представляется возможность сделать выпадающее меню блоком div с абсолютным позиционированием. Тогда нужно обозначить блок div с классом punkt как относительно позиционируемый, и в нем прописать блок div со списком подпунктов, как абсолютно позиционируемый. Для блока div со списком подпунктов определим класс "list_punkts". Этот блок нужно будет сделать невидимым, и лишь при наведении на пункт делать его видимым. Сделать первоначально его невидимым нам поможет свойство display со значением "none". В дальнейшем показывать и убирать его будем при помощи JavaScript-а, управляя все тем же свойством display. Отображаться же будет блок со списком подпунктов ниже пункта меню, и выровнен по левому краю. На данном этапе получим следующий код (для большей наглядности приведу один лишь пункт)
Код
<html>
<head>
<style>
.punkt {float:left; position:relative; }
div.list_punkts { position:absolute; top:26px; left:0px; display:none; }
</style>
</head>
<body>
<div class="menu">
<div id="block_menu">
<div class="punkt">
<div>О проекте</div>
<div class="list_punkts">
<a href="#"><div class="podpunkt">Главная</div></a>
<a href="#"><div class="podpunkt">О нас</div></a>
<a href="#"><div class="podpunkt">Контакты</div></a>
<a href="#"><div class="podpunkt">Карта сайта</div></a>
</div>
</div>
</div>
<div class="footer_menu"></div>
</div>
</body>
</html>

Ну вот, основа уже есть, можно писать и сам скрипт. Для отображения выпадающего меню при наведении курсора мышки на пункт меню будем использовать обработчик событий onMouseOver, которому укажем функцию, делающую наш блок видимым. Для скрытия выпадающего меню при уводе указателя мыши с пункта меню будем использовать обработчик событий onMouseOut, которому укажем функцию, делающую наш блок невидимым. Теперь осталось решить, как получить доступ к пункту меню и блоку со списком подпунктов. Решим эту задачу с помощью DOM (объектная модель документа). Для этого в обработчике событий передадим исполняющей функции объект пункта меню, у нас это div с классом "punkt". Реализуем подобное чудо с помощью ключевого слова "this", которое означает текущий объект, например, если мы напишем
Код
...
<div class="punkt" onMouseOver="overPunkt(this);">
...

То при вызове функции overPunkt(obj_block){ ... } переменная obj_block будет содержать объект блока div приведенного в примере.
Однако использование DOM потребует заключить текст пункта меню в блок div и повышенного внимания при наборе HTML-кода. Давайте рассмотрим уже готовый к употреблению код, а потом поясню.
Код
<html>

<head>
<title>Выпадающее меню на javascript</title>
<style>

body { font-family: verdana, sans-serif; font-size:13px; margin:0px; padding:0px;
background:#ADE7F1;}

.menu { background:#C4C2F8; width:100%; }

#block_menu { margin-left:5px; }
.punkt {float:left; padding: 1px 1px 0px 1px; background:transparent; position:relative; cursor:pointer; }
.punkt div {padding:2px 7px 2px 7px;}
div.list_punkts {background:#C6E0B6; position:absolute; top:26px; left:0px;
display:none; padding:0px; width:180px; border:solid 1px #000; }
div.list_punkts div.kont {padding:0px;margin:3px; /*background:#80FF00;*/ }

div.list_punkts a {text-decoration:none; padding:0px; cursor:pointer; color:#000080;}
div.list_punkts div a div.podpunkt { /*background:#FF8000;*/ width:100%; padding:0px; margin-top:2px; }

div.list_punkts div a div.podpunkt div { width:100%;padding:0px 0px 0px 2px; white-space:pre;}

div.list_punkts div a:hover { background:#7C58DC; }
div.list_punkts div a:hover div.podpunkt { background:#7C58DC; color:#fff; }
.footer_menu { clear:both; }

</style>
</head>
<body>

<script type="text/javascript">

function overPunkt(obj_listPunkt)
{
/* делаем выпадающее меню видимым */
obj_listPunkt.childNodes[1].style.display="block";
/* ставим выпадающее меню ниже пункта меню */
obj_listPunkt.childNodes[1].style.top=obj_listPunkt.offsetHeight;
/*дальше идет оформление пункта меню */
obj_listPunkt.style.background="#8080FF";
obj_listPunkt.style.padding=0;
obj_listPunkt.childNodes[0].style.border="solid 1px #000";
obj_listPunkt.childNodes[0].style.borderBottom="none";
/* запоминаем цвет текста пункта меню, чтоб потом его можно было восстановить */
color_text=obj_listPunkt.style.color;
obj_listPunkt.style.color="#dfd";
}

function outPunkt(obj_listPunkt)
{
/* делаем выпадающее меню невидимым */
obj_listPunkt.childNodes[1].style.display="none";
/* дальше восстанавливаем первоначальный внешний вид пункта меню */
obj_listPunkt.style.background="transparent";
obj_listPunkt.style.padding=1;
obj_listPunkt.style.paddingBottom=0;
obj_listPunkt.childNodes[0].style.border="none";
obj_listPunkt.style.color=color_text;
}

</script>

<div class="menu">
<div id="block_menu">

<div class="punkt" onMouseOver="overPunkt(this);" onMouseOut="outPunkt(this);"><div>О проекте</div
><div class="list_punkts"><div class="kont">
<a href="#"><div class="podpunkt"><div>Главная</div></div></a>
<a href="#"><div class="podpunkt"><div>О нас</div></div></a>
<a href="#"><div class="podpunkt"><div>Контакты</div></div></a>
<a href="#"><div class="podpunkt"><div>Карта сайта</div></div></a>
</div></div>
</div>

<div class="punkt" onMouseOver="overPunkt(this);" onMouseOut="outPunkt(this);"><div>Веб-дизайн</div
><div class="list_punkts"><div class="kont">
<a href="http://www.linedmk.com"><div class="podpunkt"><div>Основы</div></div></a>
<a href="#"><div class="podpunkt"><div>Статьи</div></div></a>
<a href="#"><div class="podpunkt"><div>Литература</div></div></a>
<a href="#"><div class="podpunkt"><div>Приемы и примеры</div></div></a>
<a href="#"><div class="podpunkt"><div>Частые ошибки</div></div></a>
</div></div>
</div>

<div class="punkt" onMouseOver="overPunkt(this);" onMouseOut="outPunkt(this);"><div>JavaScript</div
><div class="list_punkts"><div class="kont">
<a href="#"><div class="podpunkt"><div>Основы</div></div></a>
<a href="#"><div class="podpunkt"><div>Литература</div></div></a>
<a href="#"><div class="podpunkt"><div>Статьи</div></div></a>
<a href="#"><div class="podpunkt"><div>Скачать скрипты</div></div></a>
</div></div>
</div>

<div class="punkt" onMouseOver="overPunkt(this);" onMouseOut="outPunkt(this);"><div>PHP</div
><div class="list_punkts"><div class="kont">
<a href="#"><div class="podpunkt"><div>Основы</div></div></a>
<a href="#"><div class="podpunkt"><div>Литература</div></div></a>
<a href="#"><div class="podpunkt"><div>Статьи</div></div></a>
<a href="#"><div class="podpunkt"><div>Скачать скрипты</div></div></a>
</div></div>
</div>

<div class="punkt" onMouseOver="overPunkt(this);" onMouseOut="outPunkt(this);"><div>Новости</div
><div class="list_punkts"><div class="kont">
<a href="#"><div class="podpunkt"><div>За последнюю неделю</div></div></a>
<a href="#"><div class="podpunkt"><div>За месяц</div></div></a>
<a href="#"><div class="podpunkt"><div>Все</div></div></a>
</div></div>
</div>

</div>
<div class="footer_menu"></div>
</div>

</body>
</html>

Для того чтобы правильно работали функции обработки пункта меню и списка подпунктов, нужно блок пункта меню, блок с названием и блок со списком подпунктов писать без пробелов, при необходимости переносить текст на новую строку можно в теге, следующим образом
Код
<div class="punkt" onMouseOver="overPunkt(this);"
onMouseOut="outPunkt(this);"><div>PHP</div
><div class="list_punkts">

Однако подобный способ значительно облегчает написание, как самих функций, так и исключает некоторые действия другого рода.
При наведении пользователем курсора мышки на пункт меню, обработчик событий onMouseOver вызовет функцию overPunkt() и переменной "obj_listPunkt" будет передан объект div с классом "punkt". Согласно записанному нами HTML-коду первым дочерним объектом будет блок div с названием пункта. К нему доступ можно получить, записав следующее
Код
obj_listPunkt.childNodes[0]

Доступ к блоку div с классом "list_punkts" содержащий список подпунктов (выпадающее меню) можно получить следующим образом
Код
obj_listPunkt.childNodes[1]

Так как свойство childNodes содержит список потомков узла, и для доступа к какому-нибудь потомку нужно указать номер потомка (отсчет начинается с нуля). Что мы, вообще-то, и применили.
Если Вы знаете каскадные таблицы стилей, то уже догадались, что кроме управления видимостью выпадающего меню, в функциях overPunkt() и outPunkt() также меняется и внешний вид пункта меню, так как в HTML-коде добавлены еще элементы оформления внешнего вида меню.
Как реализовать изменение фона блока подпункта при наведении курсора мыши читайте эту статью.
Опубликовано 08 июля 2008 г.
Комментарии к публикации
Всего комментариев: 46
прохожий: Гость | 18.11.2009, 06:30 #
Спасибо !!!!!
прохожий: Гость | 19.01.2010, 21:00 #
сайт: www.maxis-dg.ru
присоединюсь
прохожий: Гость | 20.02.2010, 01:14 #
Спасибо огромное!
и если не сложно подскажите чего надо изменить чтобы меню стали вертикальным и выпадающая вкладка вылазила справа.
заранее спасибо.
Суперадмин: | 20.02.2010, 21:06 #
Для этого нужно переделывать скрипт серьезно.
прохожий: Гость | 16.03.2010, 15:54 #
Спасибо за пример. Но не так уж и серьезно надо переделывать. Убрать у пунктов меню float:left, изменить ширину их родителя до нужного значения и в overPunkt
сделать так:
obj_listPunkt.childNodes[1].style.top=0;
obj_listPunkt.childNodes[1].style.left=obj_listPunkt.offsetWidth;
===
должно работать.

Еще раз спасибо, отлично разжёвано.
прохожий: Volvoman | 17.03.2010, 00:35 #
Отличный скрипт. Но только вот вопрос...как разместить это меню по центру страницы, перепробовал все что знаю, но никак не получается...подскажите плиз.
прохожий: Max | 17.03.2010, 14:15 #
...разве что совсем не понятно, чем объясняется необходимость написания без пробелов и хитрого переноса строки. Какой источник по яваскрипту можно почитать, чтоб узнать, чем это обусловлено?
Суперадмин: | 27.03.2010, 07:59 #
Это объясняется тем, что элементы страницы представляются в виде объектной модели DOM (Document Object Model). Наберите в поисковике javascript dom и многое станет ясно. А так сделано для того, чтобы меньше было кода на javascript.
Суперадмин: | 27.03.2010, 07:56 #
Возможно получится сделать с помощью таблицы. Попробуйте поэкспериментировать.
прохожий: Vadim | 26.03.2014, 11:21 #
E-mail: написать сообщение
К примеру так:
.menu {
background:#fff;
width:70%;
height:50px;
margin:100px 15% 0px;
}
прохожий: Гость | 02.04.2010, 20:31 #
Очень неплохая статья.
прохожий: Гость | 03.04.2010, 06:36 #
Отличная статья. Все понятно даже для новичков.
Хочу только не могу поменять вид всплывающего меню, обвести его в рамку и изменить цвет.
Подскажите, как это сделать.

Спасибо.
Натали
Суперадмин: | 03.04.2010, 19:38 #
Управлять внешним видом меню надо изменяя свойства каскадных стилевых таблиц. Все они расположены в этом примере между тегом style.
прохожий: Гость | 14.04.2010, 20:45 #
сайт: net.ru
А у меня такой вопрос) на странице левый и правый фрейм....в левом выпадающее меню....левый фрейм узкий и при раскрытии второго уровня меню его не видно.....
Ответьте пожалуйста
Суперадмин: | 15.04.2010, 03:47 #
Я фреймы очень редко использую, и для других целей. Ответа на ваш вопрос я не знаю.
прохожий: Сергей | 06.05.2010, 05:06 #
А как можно сделать трехуровневое меню? Т.е. чтоб из подпунктов при наведении раскрывался еще спиок подподпунктов?
Суперадмин: | 08.05.2010, 00:08 #
На javascript :)
прохожий: Яна | 13.06.2010, 03:43 #
а как сделать чтобы меню было вертикальным?
Суперадмин: | 14.06.2010, 18:38 #
Выше в комментариях написано уже.
прохожий: Гость | 16.06.2010, 23:37 #
сайт: ccckino.ru
У меня почему-то не работает, буду ещё мучатся
прохожий: Гость | 20.06.2010, 19:19 #
В FifeFox работает не корректно.
Суперадмин: | 28.06.2010, 05:09 #
В какой версии не работает? У меня во всех установленных на компьютере FireFox-х работает нормально.
прохожий: Гость | 05.02.2011, 22:36 #
Некорректная работы в Firefox (3.6.14) и Opera (10.63)
При наведении мышки на верхний уровень меню пункт меню подсвечивается, но подпункты не выпадают. А послу ухода мышки - пункт меняю вообще исчезает из строки меню.
Я не мастер в этих делах. Что нужно изменить?
Суперадмин: | 08.02.2011, 07:25 #
Проверил в браузерах IE7, IE8, Firefox 3.5.5 и Opera 11.01 - меню нормально работает.
Что делать вам - я не знаю :)
прохожий: Валерий | 08.08.2010, 08:00 #
сайт: chebland.ru
поставил себе на сайт. замечательная штука. портаботав ещё с css прямо прелесть... но вот позникла проблема - подпункты быстро исчезают после наведения... подскажите, пожалуйста, что нужно дописать чтобы после того как с ссылки уберёшь курсор это меню держалось ещё, допустим 1 секунду? Заранее спасибо!
Суперадмин: | 10.08.2010, 03:07 #
Данный эффект можно сделать с помощью функции setTimeout(). Смотрите в этом направлении.
прохожий: Валерий | 11.08.2010, 23:36 #
сайт: chebland.ru
Подскажите, пожалуйста, какую нужно строчку с setTimeout() добавить чтобы после того как уберёшь мышку с ссылки пропало через 2 секунды? никак не могу разобраться с setTimeout()
Суперадмин: | 04.09.2010, 20:28 #
Подумайте сами ;)
прохожий: Гость | 28.08.2010, 07:23 #
сайт: tehmash94.ru
WonderWebWare CSS Menu Generator - готовая программа для выпадающего горизонтального или вертикального меню, можно подобрать цвет любой понравившийся и подходящий именно для Вашего сайта.
http://www.wonderwebware.com/css-menu/
прохожий: Дмитрий | 14.09.2010, 15:06 #
сайт: seo-cook.ru/
Я тоже WonderWebWare CSS Menu Generator пользуюсь, кроссбраузерность поддерживается
прохожий: Гость | 28.10.2010, 07:56 #
Огромное спасибо автору!
прохожий: Тамаз | 29.12.2010, 05:58 #
А как сделать,чтобы выпадающее окошко,было выше меню??
Суперадмин: | 29.12.2010, 07:59 #
Не уверен, что этот скрипт можно переделать под ваши требования. Скорее всего для этого нужен другой скрипт.
пользователь: | 13.02.2011, 05:23 #
E-mail: написать сообщение
Благодарю за очень интересный материал.
Я вот его кручу со всех сторон, но никак не получается сделать вертикальное меню, чтобы подпункты меню выпадали снизу пунктов.
Что необходимо указать в коде?
Суперадмин: | 14.02.2011, 18:57 #
Измените свойство
div.list_punkts { position:absolute; top:26px; left:0px; display:none; }

на

div.list_punkts { position:absolute; top:0px; right:0px; display:none; }
не проверял, но должно работать так.
прохожий: Александр | 03.03.2011, 03:18 #
E-mail: написать сообщение
У меня такая проблема - делаю я ща сайт в шапке сайте зделал таблицу
1 строка 1 столбец там картинка и т.п.
и 2 строка 5 столбцов (это типо меню)
в каждой картинка хочу зделать выпадающее меню на первых 2 картинках
они в разных столбцах т.е. надо делать 2 меню
так вот 1 меню делаю все ок и в EI пашет ,но вот 2 меню в EI не пашет
пытался линковать 2 ксс таблицы писал каждому айди свое но 2 меню не выпадает (

Помогите уже все излазил не могу не че зделать

вот эти 2 столбца
<ul id="cssmenu">
<li><a href="#"><center><img border="0" src="картинки/Главная/Биография.jpg" width="238" height="36"></center></a>
<ul dynamicoutline>
<li><a href="biog.html">Краткая хронология</a></li>
<li><a href="детство.html">Детство</a></li>
<li><a href="Mos.html">Путешествие в Москву</a></li>
<li><a href="#">Петербурская Академия</a></li>
<li><a href="#">Ломоносов за границей</a></li>
<li><a href="#">Труды в Академии наук</a></li>

</li>
</td>
<td height="25" width="250">

<ul id="csssmenu">
<li><a href="#"><img border="0" src="картинки/Главная/Произведения1.jpg" width="252" height="36"></a>
<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>

</ul>
</li>
Суперадмин: | 04.03.2011, 02:26 #
Разберитесь внимательно, как работает меню. Вам нужно прописать для пунктов второго меню параметры

onMouseOver="overPunkt(this);"
onMouseOut="outPunkt(this);

по аналогии с первым меню.
прохожий: Юрий | 07.05.2011, 02:19 #
А неподскажите, как сделать так, чтобы выпадающее меню появлялось после "клика" и оставалось выдимым до тех пор, пока второй раз не нажмешь левую кнопку "мыши" ?
Суперадмин: | 08.05.2011, 18:22 #
Можно сделать. Но ответ ищите или в Яндексе или Google.
прохожий: Прохожий | 08.11.2011, 07:33 #
Спасибо! Отличная статья!
прохожий: Я | 28.11.2011, 04:41 #
E-mail: написать сообщение
А можно упростить и облегчить все ...

<html>

<head>
<title>Выпадающее меню на javascript</title>
<style>

body { font-family: verdana, sans-serif; font-size:13px; margin:0px; padding:0px;
background:#ADE7F1;}

.menu { background:#C4C2F8; width:100%; }

#block_menu { margin-left:5px; }



.mnu
{
float:left;
width:auto;
height:auto;
display:block;
margin-left:20px;
}


.mnu_popup
{
display:block;
position:absolute;
height:auto;
display:none;
background-color:#096;
}

.mnu_popup a
{
display:block;
width:auto;
height:auto;
}

.mnu_popup a:hover
{
background-color:#999;
}


</style>
</head>
<body>

<script type="text/javascript">


function over_m(sender,n)
{
document.getElementById("m"+n).style.display="block";
}

function out_m(sender,n)
{
document.getElementById("m"+n).style.display="none";
}

</script>

<div class="menu">
<div id="block_menu">

<div class="mnu" onMouseOver="over_m(this,1);" onMouseOut="out_m(this,1);">
<a href="">Веб-дизайн</a><BR>
<div class="mnu_popup" id="m1">
<a href="http://www.linedmk.com">Основы</a>
<a href="#">Статьи</a>
<a href="#">Литература</a>
<a href="#">Приемы и примеры</a>
<a href="#">Частые ошибки</a>
</div>
</div>

<div class="mnu" onMouseOver="over_m(this,2);" onMouseOut="out_m(this,2);">
<a href="">Веб-дизайн</a><BR>
<div class="mnu_popup" id="m2">
<a href="http://www.linedmk.com">Основы</a>
<a href="#">Статьи</a>
<a href="#">Литература</a>
<a href="#">Приемы и примеры</a>
<a href="#">Частые ошибки</a>
</div>
</div>

</div>
<div class="footer_menu"></div>
</div>

</body>
</html>
прохожий: German | 22.02.2013, 21:00 #
Спасибо за скрипт, сделал на его основе меню. Но вот что заметил, в опере если резко повести мышкой внутри меню, то оно закрывается. У меня меню из 5 элементов, навожу на заголовок меню, оно открывается, двигаю мышку к 4му элементу и меню сразу закрывается. Подобная картина еще наблюдается если потихоньку вниз до последнего пункта довести и потом вверх начать двигать. В мозилле такого не замечено.
прохожий: Neo | 11.06.2013, 12:22 #
Код не работает!!!
Меню появляется, и сразу же исчезает, если попытаться подвинуть стрелочку вниз.
прохожий: RGBPlus | 11.08.2014, 16:37 #
Смотрите CSS, там собака зарыта
прохожий: Я | 14.12.2013, 19:11 #
E-mail: написать сообщение
Спасибо за скрипт!
Только у меня такая проблема...между пунктом и подпунктом почему-то отображается зазор (т.е. расстояние), из-за чего при переходе на подпункт, указатель попадает на пустое место и выпадающее меню сразу закрывается...как это исправить? Подскажите кто-нибудь, плиз!!!
прохожий: Анонимус | 01.04.2015, 18:55 #
Ужасная вёрстка. Кто div в a запихивает? Блочный элемент в строчный. Больной что ли?
Вход в аккаунт
Новости сайта