Горизонтальное выпадающее меню на jQuery

Сегодня я расскажу как легко сделать горизонтальное выпадающее меню на jQuery. В силу его понятности и простоты его можно быстро приспособить к любому дизайну. Например, буквально сегодня, я вставил такое горизонтальное меню в проект на CMS Битрикс. К слову, этот скрипт входит в мою копилку сниппетов.

Html-код меню должен иметь такой вид:

<ul id="jsddm">
    <li> <a href="#">JavaScript</a>
        <ul>
            <li><a href="#">Выпадающее меню</a></li>
            <li><a href="#">jQuery</a></li>
            <li><a href="#">Ajax</a></li>
        </ul>
    </li>
    <li> <a href="#">Эффекты</a>
        <ul>
            <li><a href="#">Slide эффект</a></li>
            <li><a href="#">Fade эффект</a></li>
        </ul>
    </li>
    <li><a href="#">Навигация</a></li>
    <li><a href="#">HTML/CSS</a></li>
    <li><a href="#">Помощь</a></li>
</ul>

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

#jsddm {
    margin: 0;
    padding: 0;
}

#jsddm li {
    float: left;
    list-style: none;
    font: 12px Tahoma, Arial;
}

#jsddm li a {
    display: block;
    background: #20548E;
    padding: 5px 12px;
    text-decoration: none;
    border-right: 1px solid white;
    width: 70px;
    color: #EAFFED;
    white-space: nowrap;
}

#jsddm li a:hover {
    background: #1A4473;
}

#jsddm li ul {
    margin: 0;
    padding: 0;
    position: absolute;
    visibility: hidden;
    border-top: 1px solid white;
}

#jsddm li ul li {
    float: none;
    display: inline;
}

#jsddm li ul li a {
    width: auto;
    background: #9F1B1B;
}
#jsddm li ul li a:hover {
    background: #7F1616;
}

А вот и сам скрипт. Обработчики событий привязываются к элементам LI. При наведении на пункт меню скрываем предыдущий открытый вложенный список (если виден) и открываем новый. Когда курсор убираем  — ждем 500мс и закрываем список.

var timeout    = 500;
var closetimer = 0;
var ddmenuitem = 0;

function jsddm_open() {
    jsddm_canceltimer();
    jsddm_close();
    ddmenuitem = $(this).find('ul').css('visibility', 'visible');
}

function jsddm_close() {
    if (ddmenuitem) ddmenuitem.css('visibility', 'hidden');
}

function jsddm_timer() {
    closetimer = window.setTimeout(jsddm_close, timeout);
}

function jsddm_canceltimer() {
    if (closetimer) {
        window.clearTimeout(closetimer);
        closetimer = null;
    }
}

$(document).ready(function() {
    $('#jsddm > li').bind('mouseover', jsddm_open);
    $('#jsddm > li').bind('mouseout',  jsddm_timer);
});
document.onclick = jsddm_close;

Как видите, все действительно просто, а главное кроссбраузерно: IE6+, Firefox 1.5+, Opera 8+, Safari 3+, Chrome 0.2+

Смотрите ДЕМО.

За скрипт спасибо Javascript Array

Метки: , , ,

Комментарии

  1. Dmitry 03.08.2010 в 09:47 #

    В чем преимущество решения на jQuery перед CSS-меню?

  2. Vadyos 05.08.2010 в 13:36 #

    Недавно создал блог по скриптах на JQuery. Если кому то будет интересно то вот ссылка — vadyos.org.ua

  3. Ed.gar 31.08.2010 в 20:11 #

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

    дополнительный яваскрипт и подключение jquery — избыточное решение.

  4. vinaction 12.09.2010 в 21:42 #

    А меня волнует вопрос — как вы реализовали на главной странице слайд шоу со ссылками на статьи?

    Использовали какой то плагин? Или ваше детище? :)

    Заранее спасибо за ответ!

    • Neolot 13.09.2010 в 17:27 #

      Нет, не плагин. Это jQuery Cycle plugin + немного WordPress API + использование возможностей WordPress 3.0

      • vinaction 13.09.2010 в 20:55 #

        Спасибо за ответ!

        Не планируете сделать про это такой же развернутый пост как про Горизонтальное выпадающее меню?

        Я думаю, что не я один был бы очень вам за это благодарен!

        • Neolot 13.09.2010 в 21:09 #

          Думаю да, можно сделать такой пост. Правда, получится он не маленький, особенно если немного углубится в теорию)

  5. vinaction 14.09.2010 в 21:36 #

    С нетерпением буду ждать :)

  6. Nigelist 23.11.2010 в 13:17 #

    А можно ли сделать чтобы скрытые элементы меню выпадали плавно?

  7. Вадим 31.01.2011 в 22:27 #

    По не понятным мне причинам пример не работает(скопировал все как здесь). Что не так?

  8. Sheckler 03.02.2011 в 17:19 #

    Библиотеку jquery подключи

  9. Albedo 18.02.2011 в 09:25 #

    А в CSS обязательно менять? Только в main.tpl не пойдет?

  10. Виталий 27.03.2011 в 12:29 #

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

    • Neolot 27.03.2011 в 16:06 #

      Задайте ширину для #jsddm и назначьте ему margin: 0 auto

  11. Дмитрий 29.05.2011 в 10:52 #

    Кошмар, через таймер... Да и стиль кода ужасен :) )))

    вот классический пример в одну функцию без таймера и прочих ненужностей habrahabr.ru/blogs/jquery/39440/ (Drop-down меню)

    • Se7eN 30.08.2011 в 20:07 #

      а в чем кошмар с использованием таймера, глючно или что? обьясните, у меня как раз с ним на сайте используется, думаете переделать?

      • Neolot 30.08.2011 в 21:17 #

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

  12. Scan 20.06.2011 в 11:23 #

    Делаю так:

    function SMenu_show() {
    	$(this).children('.sub').show();
    }
    function SMenu_hide() {
    	$(this).children('.sub').hide();
    }
    $('.ddmenu li').bind('mouseenter', SMenu_show);
    $('.ddmenu li').bind('mouseleave', SMenu_hide);

    Работает без таймеров.

  13. Александр 01.09.2011 в 14:16 #

    А как использовать данный код для того чтобы вывести меню на WordPress? Просто вставил код, стили к нему, но меню не стало выпадающим. Имеются страницы, которые являются дочерними для другой страницы, но они в меню не выпадают.

    narodnieoknant.ru

    Вот сайт на котором я все это пробую. В пункте «Товары» должно быть два подпункта: «Окна» и «Лоджии», но они не выводятся.

    Заранее благодарю за ответ!

    • Neolot 01.09.2011 в 14:21 #

      У вас ul имеет id="dd", а должно быть id="jsddm". Поправьте или в скрипте, или в меню.

      • Александр 01.09.2011 в 14:38 #

        Всплывающие меню появились. Благодарю за помощь. Но как только указал нужный Id сразу же пропали стили оформления. Меню выровнялось по левому краю. В стилях ширина меню указана и задан margin:0 auto;

        • Neolot 01.09.2011 в 14:42 #

          Ну со своей версткой вы уж как-нибудь сами разберитесь

          • Александр 01.09.2011 в 14:43 #

            И почему-то на примере пункты находятся друг под другом, а у меня они слеплены в едино. Это тоже проблемы верстки?

          • Neolot 01.09.2011 в 14:45 #

            Да, скрипт только делает меню выпадающим, а как оно выглядит визуально прописано в ваших стилях.

  14. Антон 04.10.2011 в 15:31 #

    Большое спасибо все сделал, но 1 проблема, в опере все ок, а вот в хроме и фаерфоксе когда меню выпало, она находится как бы под рекламой от гугл адсенс который находится ниже. Как такое исправить?

    • Neolot 04.10.2011 в 15:40 #

      Дело в том, что объект флэш всегда ложится поверх любого объекта на странице, поэтому выпадающее меню оказывается под ним. Чтобы решить проблему в таких случаях нужно использовать специальный параметр вызова объекта, но в adsense нельзя задавать параметры флэш. Придется либо отключить показ баннеров в этом месте, или убрать/перенести рекламный блок.

  15. Антон 04.10.2011 в 16:33 #

    Оперативно вы отвечаете :) спасибо.

    Пришлось перенести блок рекламы, не очень конечно хотелось мне этого, но меню хочется больше.

  16. ДМ 28.10.2011 в 20:46 #

    Можно это же меню генерировать чуть проще:

    function makeMenu(holder) {
    	var closeTimer = null;
    	var closeInterval = 300;
    
    	$(holder).children('li').mouseover(function() {
    		$(holder + ' li ul').hide();
    		$(this).children('ul').show();
    		if(closeTimer) {
    			window.clearTimeout(closeTimer);
    			closeTimer = 0;
    		}
    	});
    	$(holder + ' li').mouseout(function() {
    		if(!closeTimer) {
    			closeTimer = window.setTimeout('$("' + holderId + ' li ul").hide();', closeInterval);
    		}
    	});
    }
    
    $(document).ready(function() {
    	makeMenu('#jsddm');
    }

  17. Сергей 22.11.2011 в 20:32 #

    Спасибо немного доработал и сделал посвоему! :)

  18. Катя 11.01.2012 в 13:55 #

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

    • Neolot 11.01.2012 в 17:42 #

      После строки

      $('#jsddm > li').bind('mouseout',  jsddm_timer);

      добавьте строку

      $('#jsddm > li ul li:odd').addClass('odd');

Ваше мнение

Если вам нужно вставить код, оберните его в специальный шорткод [php], [html], [css], [js].
Например: [js]Ваш код[/js]