Как сделать так, чтобы всплывающее меню Twitter Bootstrap при наведении курсора, а не при нажатии - PullRequest
1122 голосов
/ 16 января 2012

Я бы хотел, чтобы меню Bootstrap автоматически выпадало при наведении курсора, а не щелкало заголовок меню. Я также хотел бы потерять маленькие стрелки рядом с заголовками меню.

Ответы [ 41 ]

901 голосов
/ 16 января 2012

Чтобы меню автоматически появлялось при наведении, это можно сделать с помощью базового CSS. Вам нужно выбрать селектор для опции скрытого меню, а затем настроить его на отображение в виде блока, когда наведен соответствующий тег li. Если взять пример со страницы начальной загрузки Twitter, селектор будет выглядеть следующим образом:

ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;    
}

Однако, если вы используете адаптивные функции Bootstrap, вам не понадобятся эти функции на свернутой панели навигации (на экранах меньшего размера). Чтобы избежать этого, оберните код выше в медиа-запрос:

@media (min-width: 979px) {
  ul.nav li.dropdown:hover > ul.dropdown-menu {
    display: block;
  }
}

Чтобы скрыть стрелку (каретку), это делается по-разному в зависимости от того, используете ли вы Twitter Bootstrap версии 2 и ниже или версию 3:

Bootstrap 3

Чтобы удалить каретку в версии 3, вам просто нужно удалить HTML <b class="caret"></b> из элемента привязки .dropdown-toggle:

<a class="dropdown-toggle" data-toggle="dropdown" href="#">
    Dropdown
    <b class="caret"></b>    <-- remove this line
</a>

Bootstrap 2 и ниже

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

a.menu:after, .dropdown-toggle:after {
    content: none;
}

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

Спасибо @CocaAkat за указание на то, что нам не хватало дочернего комбинатора ">" для предотвращения отображения подменю при наведении на родительский элемент

565 голосов
/ 13 апреля 2012

Я создал раскрывающееся меню при наведении, основанное на последней (v2.0.2) платформе Bootstrap, которая поддерживает несколько подменю, и решил опубликовать ее для будущих пользователей:

body {
  padding-top: 60px;
  padding-bottom: 40px;
}

.sidebar-nav {
  padding: 9px 0;
}

.dropdown-menu .sub-menu {
  left: 100%;
  position: absolute;
  top: 0;
  visibility: hidden;
  margin-top: -1px;
}

.dropdown-menu li:hover .sub-menu {
  visibility: visible;
}

.dropdown:hover .dropdown-menu {
  display: block;
}

.nav-tabs .dropdown-menu,
.nav-pills .dropdown-menu,
.navbar .dropdown-menu {
  margin-top: 0;
}

.navbar .sub-menu:before {
  border-bottom: 7px solid transparent;
  border-left: none;
  border-right: 7px solid rgba(0, 0, 0, 0.2);
  border-top: 7px solid transparent;
  left: -7px;
  top: 10px;
}

.navbar .sub-menu:after {
  border-top: 6px solid transparent;
  border-left: none;
  border-right: 6px solid #fff;
  border-bottom: 6px solid transparent;
  left: 10px;
  top: 11px;
  left: -6px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet" />

<div class="navbar navbar-fixed-top">
  <div class="navbar-inner">
    <div class="container-fluid">
      <a data-target=".nav-collapse" data-toggle="collapse" class="btn btn-navbar">
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </a>
      <a href="#" class="brand">Project name</a>
      <div class="nav-collapse">
        <ul class="nav">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li><a href="#">Link</a></li>
          <li class="dropdown">
            <a data-toggle="dropdown" class="dropdown-toggle" href="#">Dropdown <b class="caret"></b></a>
            <ul class="dropdown-menu">
              <li>
                <a href="#">2-level Dropdown <i class="icon-arrow-right"></i></a>
                <ul class="dropdown-menu sub-menu">
                  <li><a href="#">Action</a></li>
                  <li><a href="#">Another action</a></li>
                  <li><a href="#">Something else here</a></li>
                  <li class="divider"></li>
                  <li class="nav-header">Nav header</li>
                  <li><a href="#">Separated link</a></li>
                  <li><a href="#">One more separated link</a></li>
                </ul>
              </li>
              <li><a href="#">Another action</a></li>
              <li><a href="#">Something else here</a></li>
              <li class="divider"></li>
              <li class="nav-header">Nav header</li>
              <li><a href="#">Separated link</a></li>
              <li><a href="#">One more separated link</a></li>
            </ul>
          </li>
        </ul>
        <form action="" class="navbar-search pull-left">
          <input type="text" placeholder="Search" class="search-query span2">
        </form>
        <ul class="nav pull-right">
          <li><a href="#">Link</a></li>
          <li class="divider-vertical"></li>
          <li class="dropdown">
            <a class="#" href="#">Menu</a>
          </li>
        </ul>
      </div>
      <!-- /.nav-collapse -->
    </div>
  </div>
</div>

<hr>

<ul class="nav nav-pills">
  <li class="active"><a href="#">Regular link</a></li>
  <li class="dropdown">
    <a href="#" data-toggle="dropdown" class="dropdown-toggle">Dropdown <b class="caret"></b></a>
    <ul class="dropdown-menu" id="menu1">
      <li>
        <a href="#">2-level Menu <i class="icon-arrow-right"></i></a>
        <ul class="dropdown-menu sub-menu">
          <li><a href="#">Action</a></li>
          <li><a href="#">Another action</a></li>
          <li><a href="#">Something else here</a></li>
          <li class="divider"></li>
          <li class="nav-header">Nav header</li>
          <li><a href="#">Separated link</a></li>
          <li><a href="#">One more separated link</a></li>
        </ul>
      </li>
      <li><a href="#">Another action</a></li>
      <li><a href="#">Something else here</a></li>
      <li class="divider"></li>
      <li><a href="#">Separated link</a></li>
    </ul>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
  <li class="dropdown">
    <a href="#">Menu</a>
  </li>
</ul>

Демо

228 голосов
/ 24 февраля 2012

В дополнение к ответу из «Голова болит» (это было здорово):

ul.nav li.dropdown:hover ul.dropdown-menu{
    display: block;    
}

Есть 2 проблемы:

  1. При нажатии на выпадающую ссылку откроется выпадающее меню. И он останется открытым, если пользователь не щелкнет где-то еще или не наведет на него курсор назад, создав неудобный пользовательский интерфейс.
  2. Между раскрывающейся ссылкой и выпадающим меню есть отступ в 1 пиксель. Это приводит к тому, что выпадающее меню становится скрытым, если вы медленно перемещаетесь между выпадающим меню и выпадающим меню.

Решением (1) является удаление элементов "class" и "data-toggle" из ссылки nav

<a href="#">
     Dropdown
     <b class="caret"></b>
</a>

Это также дает вам возможность создать ссылку на вашу родительскую страницу - что было невозможно при реализации по умолчанию. Вы можете просто заменить "#" на любую страницу, которую вы хотите отправить пользователю.

Решением (2) является удаление отступа на полях в селекторе .dropdown-menu

.navbar .dropdown-menu {
 margin-top: 0px;
}
127 голосов
/ 22 мая 2012

Я использовал немного jQuery:

// Add hover effect to menus
jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
});
69 голосов
/ 31 января 2014

Здесь много действительно хороших решений.Но я думал, что я пойду вперед и поставлю свою здесь в качестве другой альтернативы.Это всего лишь простой фрагмент jQuery, который делает это так, как при начальной загрузке, если он поддерживает всплывающие окна вместо всплывающих окон.Я только что проверил это с версией 3, поэтому я не знаю, будет ли это работать с версией 2. Сохраните его как фрагмент в вашем редакторе и сделайте это одним нажатием клавиши.

<script>
    $(function() {
        $(".dropdown").hover(
            function(){ $(this).addClass('open') },
            function(){ $(this).removeClass('open') }
        );
    });
</script>

По сути, он просто говорит, что когда вы наводите курсор на выпадающий класс, он добавляет к нему открытый класс.Тогда это просто работает.Когда вы перестаете зависать на родительском li с выпадающим классом или на дочернем ul / li, он удаляет открытый класс.Очевидно, что это только одно из многих решений, и вы можете добавить его, чтобы оно работало только с конкретными экземплярами .dropdown.Или добавьте переход к родительскому или дочернему элементу.

67 голосов
/ 05 апреля 2014

Просто настройте свой стиль CSS в три строки кода

.dropdown:hover .dropdown-menu {
   display: block;
}
22 голосов
/ 28 сентября 2014

Если у вас есть элемент с классом dropdown, например, таким:

<ul class="list-unstyled list-inline">
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-bars"></i> Dropdown 1</a>
        <ul class="dropdown-menu">
            <li><a href="">Item 1</a></li>
            <li><a href="">Item 2</a></li>
            <li><a href="">Item 3</a></li>
            <li><a href="">Item 4</a></li>
            <li><a href="">Item 5</a></li>
        </ul>
    </li>
    <li class="dropdown">
        <a data-toggle="dropdown" href="#"><i class="fa fa-user"></i> Dropdown 2</a>
        <ul class="dropdown-menu">
            <li><a href="">Item A</a></li>
            <li><a href="">Item B</a></li>
            <li><a href="">Item C</a></li>
            <li><a href="">Item D</a></li>
            <li><a href="">Item E</a></li>
        </ul>
    </li>
</ul>

Затем можно использовать раскрывающееся меню для автоматического раскрытия при наведении курсора, а не щелкать его заголовок, используя этот фрагмент кода jQuery:

<script>
    $('.dropdown').hover(
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn();
        },
        function() {
            $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut();
        }
    );

    $('.dropdown-menu').hover(
        function() {
            $(this).stop(true, true);
        },
        function() {
            $(this).stop(true, true).delay(200).fadeOut();
        }
    );
</script>

Вот демоверсия

Этот ответ основывался на @ Майкл ответ , я внес некоторые изменения и добавил некоторые дополнения для правильной работы раскрывающегося меню

20 голосов
/ 12 октября 2012

[Обновление] Плагин включен GitHub , и я работаю над некоторыми улучшениями (например, использование только с атрибутами данных (JS не требуется). Я оставляю кодниже, но это не то же самое, что на GitHub.

Мне понравилась чисто CSS-версия, но приятно иметь задержку до ее закрытия, так как обычно она лучше для пользователя (то есть не наказывается заскольжение мыши, которое выходит на 1 пиксель за пределы раскрывающегося списка и т. д.), и, как уже упоминалось в комментариях, существует 1пкс поля, с которым вам приходится иметь дело, или иногда навигация неожиданно закрывается при переходе к раскрывающемуся списку с исходной кнопки и т. д..

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

JS

// outside the scope of the jQuery plugin to
// keep track of all dropdowns
var $allDropdowns = $();

// if instantlyCloseOthers is true, then it will instantly
// shut other nav items when a new one is hovered over
$.fn.dropdownHover = function(options) {

    // the element we really care about
    // is the dropdown-toggle's parent
    $allDropdowns = $allDropdowns.add(this.parent());

    return this.each(function() {
        var $this = $(this).parent(),
            defaults = {
                delay: 500,
                instantlyCloseOthers: true
            },
            data = {
                delay: $(this).data('delay'),
                instantlyCloseOthers: $(this).data('close-others')
            },
            options = $.extend(true, {}, defaults, options, data),
            timeout;

        $this.hover(function() {
            if(options.instantlyCloseOthers === true)
                $allDropdowns.removeClass('open');

            window.clearTimeout(timeout);
            $(this).addClass('open');
        }, function() {
            timeout = window.setTimeout(function() {
                $this.removeClass('open');
            }, options.delay);
        });
    });
};  

Параметр delay довольно понятен, и instantlyCloseOthers мгновенно закроет все другие раскрывающиеся списки, которые открываются при наведении курсора нановый.

Не чистый CSS, но, надеюсь, он поможет кому-то еще в этот поздний час (т. е. это старый поток).

Если хотите, вы можете увидеть различные процессы, которые я прошелчерез (в обсуждении #concrete5 IRC), чтобы заставить его работать через различные шаги в этой сути: https://gist.github.com/3876924

Подход с использованием шаблона плагинов намного чище для поддержки отдельных таймеров и т. д.

Подробнее читайте в блоге .

15 голосов
/ 06 октября 2015

Это сработало для меня:

.dropdown:hover .dropdown-menu {
    display: block;
}
11 голосов
/ 18 ноября 2017

Это встроено в Bootstrap 3. Просто добавьте это в свой CSS:

.dropdown:hover .dropdown-menu {
display: block;
}
...