Cómo hacer que el menú desplegable de Twitter Bootstrap se desplace en lugar de hacer clic


1184

Me gustaría que mi menú Bootstrap se despliegue automáticamente al pasar el mouse por encima, en lugar de tener que hacer clic en el título del menú. También me gustaría perder las pequeñas flechas al lado de los títulos del menú.


99
Hay una solución para eso, por lo que la respuesta de mikko es correcta, pero ahora está cubierta con un complemento específico para esa situación. bootstrap-hover-dropdown
HenryW

2
Vea mi plugin apropiado recientemente publicado que evita los problemas de las siguientes soluciones CSS y js, y funciona bien en iOS y en navegadores de escritorio modernos con eventos táctiles. Incluso los atributos aria funcionan bien con eso: github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover
István Ujj-Mészáros

Hice un menú desplegable CSS3 puro con una barra de navegación de arranque. Echa un vistazo en el menú desplegable CSS3 puro de
CodePen

18
Piensa dos veces si realmente lo necesitas? Bootstrap está utilizando sitios adaptativos. Significa que también se usarán en dispositivos con controles táctiles. Por eso está diseñado de esta manera. No hay "desplazamiento" en las pantallas táctiles.
Serj

Posible duplicado de Bootstrap Dropdown con Hover
slugster

Respuestas:


592

Creé un menú desplegable puro al pasar el ratón basado en el último marco Bootstrap (v2.0.2) que tiene soporte para múltiples submenús y pensé que lo publicaría para futuros usuarios:

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>

Manifestación


54
es una decisión de diseño en bootstrap no abrir los
menús

18
¡tan bueno! También eliminé class="dropdown-toggle" data-toggle="dropdown"para que solo se desplace, no haga clic, activaría el menú. Tenga en cuenta que cuando usa estilos receptivos, los menús aún se desplazan hacia el pequeño botón en la parte superior derecha, que aún se activa con un clic. ¡Muchas gracias!
ptim

11
Para evitar el menú desplegable automático en dispositivos más pequeños (como teléfonos) y solo permitirlo a partir de un ancho mínimo de, por ejemplo, 768px do @media (min-width: 768px) {.dropdown-menu li:hover .sub-menu {visibility: visible;}}y@media (min-width: 768px) {.dropdown:hover .dropdown-menu {display: block;}}
Chris Aelbrecht

1
También para hacer clic en el enlace con niños, debe eliminar la etiqueta "data-toggle = 'dropdown'" en la etiqueta <a>.
joan16v

2
Aquí hay un código que funciona con la última versión de Bootstrap 3: jsfiddle.net/sgruenwald/2tt8f8xg
Stefan Gruenwald

910

Para hacer que el menú se coloque automáticamente al pasar el mouse sobre este, esto se puede lograr usando CSS básico. Debe calcular el selector para la opción de menú oculta y luego configurarlo para que se muestre como bloque cuando se coloca la lietiqueta correspondiente . Tomando el ejemplo de la página de arranque de Twitter, el selector sería el siguiente:

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

Sin embargo, si está utilizando las funciones de respuesta de Bootstrap, no querrá esta funcionalidad en una barra de navegación contraída (en pantallas más pequeñas). Para evitar esto, envuelva el código anterior en una consulta de medios:

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

Para ocultar la flecha (intercalar), esto se hace de diferentes maneras dependiendo de si está utilizando Twitter Bootstrap versión 2 y versiones inferiores o 3:

Bootstrap 3

Para eliminar el cursor en la versión 3 solo necesita eliminar el HTML <b class="caret"></b>del .dropdown-toggleelemento de anclaje:

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

Bootstrap 2 y más bajo

Para eliminar el símbolo de intercalación en la versión 2, necesita un poco más de información sobre CSS y le sugiero que mire con :aftermás detalle cómo funciona el pseudo elemento. Para comenzar su camino hacia la comprensión, para apuntar y eliminar las flechas en el ejemplo de arranque de Twitter, usaría el siguiente selector y código CSS:

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

Funcionará a tu favor si miras más a fondo cómo funcionan y no solo usas las respuestas que te he dado.

Gracias a @CocaAkat por señalar que nos faltaba el ">" combinador secundario para evitar que se muestren submenús en el elemento emergente principal


79
También tuve que agregar margin: 0;, de lo contrario, el margen de 1px anterior .dropdown-menucausa un comportamiento defectuoso.
Salman von Abbas

12
Solución simple, pero aún no se puede hacer clic en el enlace principal. Estoy usando el último bootstrap con el tema de raíces.
Krunal

55
Nota: Sí, esto funcionará en cualquier navegador que admita Twitter Bootstrap. @GeorgeEdison Esto es CSS básico: ¿qué parte no sería compatible con IE8? Si tiene problemas, publique una pregunta, sin comentarios engañosos.
Me duele la cabeza el

3
@ MyHeadHurts: Después de un poco más de investigación, resulta que este fue realmente un error de Bootstrap y solo se solucionó hace cinco días.
Nathan Osman

55
@Krunal para poder hacer clic en el enlace, debe eliminar el data-toggle="dropdown"atributo.
Pherrymason

231

Además de la respuesta de "Me duele la cabeza" (que fue genial):

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

Hay 2 problemas persistentes:

  1. Al hacer clic en el enlace desplegable, se abrirá el menú desplegable. Y permanecerá abierto a menos que el usuario haga clic en otro lugar o se desplace sobre él, creando una UI incómoda.
  2. Hay un margen de 1 px entre el enlace desplegable y el menú desplegable. Esto hace que el menú desplegable se oculte si se mueve lentamente entre el menú desplegable y el menú desplegable.

La solución para (1) es eliminar los elementos "clase" y "alternar datos" del enlace de navegación

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

Esto también le brinda la posibilidad de crear un enlace a su página principal, lo que no era posible con la implementación predeterminada. Simplemente puede reemplazar el "#" con la página que desee enviar al usuario.

La solución a (2) es eliminar el margen superior del selector .dropdown-menu

.navbar .dropdown-menu {
    margin-top: 0px;
}

15
Para arreglar el clic deliberado, simplemente eliminé el data-toggle="dropdown"atributo, que parecía funcionar.
Anthony Briggs

55
La solución (2) para los botones de navegación píldoras:.nav-pills .dropdown-menu { margin-top: 0px; }
Loren

1
Para solucionar el problema que mencioné anteriormente li.dropdown: hover> ul.dropdown-menu
Archimedes Trajano el

12
eliminar los atributos "clase" y "alternar datos" de los enlaces de navegación hace que deje de funcionar bien en dispositivos móviles y tabletas :(
Mosijava

1
Si eliminó el atributo data-toggle = "dropdown", no podrá expandir el menú desplegable con el teclado. Por lo tanto, no será compatible con 508. ¿Cómo puede deshabilitar el clic pero mantener la funcionalidad del teclado?
duyn9uyen

130

He usado un poco de 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();
});

13
Me gusta esto. Estoy usando JQuery de todos modos con las cosas de Bootstrap y todavía permite la funcionalidad predeterminada 'clic' en dispositivos con pantalla táctil.
Pato en Natillas

Usé esto. Me gusta que todavía permita la funcionalidad de clic, para móviles, pero para escritorios el desplazamiento es perfecto.
Stuart

1
Usé esto, pero también lo extendí para que sea utilizable en menús desplegables que no están en una navegación. Agregué clase dropdown-hover al btn-group div y usé este jQuery finder $ ('ul.nav li.dropdown, .dropdown-hover'). Hover (function () {. ¡Gracias!
Brandon

Usé este, bonito y pequeño. La versión css no permitía que el submenú permaneciera visualizado, y 200 ms era demasiado rápido, así que lo cambié a $('ul.nav li.dropdown').hover(function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn(); }, function() { $(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut().hover(function() { $(this).stop(true, true); }); });: Cuando el submenú esté suspendido, deje de desvanecerse
Damien el

esto no parece funcionar con jqLite que se incluye con anguraljs
nuander

70

Aquí hay muchas soluciones realmente buenas. Pero pensé que seguiría adelante y pondría el mío aquí como otra alternativa. Es solo un simple fragmento de jQuery que lo hace de la forma en que lo haría bootstrap si admitiera el desplazamiento de los menús desplegables en lugar de simplemente hacer clic. Solo he probado esto con la versión 3, así que no sé si funcionaría con la versión 2. Guárdelo como un fragmento en su editor y téngalo presionando una tecla.

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

Básicamente, solo dice que cuando pasas el mouse sobre la clase desplegable, agregará la clase abierta. Entonces simplemente funciona. Cuando dejas de desplazarte por el li principal con la clase desplegable o el ul / li secundario, se elimina la clase abierta. Obviamente, esta es solo una de las muchas soluciones, y puede agregarla para que funcione solo en instancias específicas de .dropdown. O agregue una transición a padre o hijo.


2
¡Gran solución! También eliminé el atributo data-toggle = "dropdown" del enlace para poder hacer clic en el enlace superior.
Sergey

Ese es un buen consejo Sergey. Siempre me aseguro de que el enlace superior no vaya a ninguna parte para que funcione también en tabletas y teléfonos.
stereoscience

1
@Sergey No recomendaría hacer eso. Rompería la funcionalidad para usuarios móviles. No pueden usar la función de desplazamiento para abrir un menú y deben poder hacer clic en él.
Paul

2
Esto es increíblemente corto y fácil, a la vez que sigue siendo compatible con las pantallas táctiles. Debería ser votado mucho más.
Max

Esto se ve muy bien. ¿Alguna idea de cómo agregar un poco de animación usando transiciones CSS?
Fred Rocha

70

Simplemente personalice su estilo CSS en tres líneas de código

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

22

Si tiene un elemento con una dropdownclase como esta (por ejemplo):

<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>

Luego, puede hacer que el menú desplegable se despliegue automáticamente al pasar el mouse por encima, en lugar de tener que hacer clic en su título, utilizando este fragmento de código 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>

Aquí hay una demostración

Esta respuesta se basó en la respuesta de @Michael , he realizado algunos cambios y agregado algunas adiciones para que el menú desplegable funcione correctamente


Perfecto. Muchas gracias.
antikbd

20

[Actualización] El complemento está en GitHub y estoy trabajando en algunas mejoras (como usar solo con atributos de datos (no es necesario JS). Dejé el código a continuación, pero no es lo mismo que lo que está en GitHub.

Me gustó la versión puramente CSS, pero es bueno tener un retraso antes de que se cierre, ya que generalmente es una mejor experiencia de usuario (es decir, no se castiga por un deslizamiento del mouse que va 1 px fuera del menú desplegable, etc.), y como se menciona en los comentarios , hay un margen de 1px con el que tiene que lidiar o, a veces, el navegador se cierra inesperadamente cuando se mueve al menú desplegable desde el botón original, etc.

Creé un pequeño complemento rápido que he usado en un par de sitios y funcionó muy bien. Cada elemento de navegación se maneja de forma independiente, por lo que tienen sus propios temporizadores de retraso, etc.

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);
        });
    });
};  

El delayparámetro se explica por sí mismo, e instantlyCloseOthersinstantáneamente cerrará todos los demás menús desplegables que estén abiertos al pasar el mouse sobre uno nuevo.

No es CSS puro, pero espero que ayude a alguien más a estas horas de la noche (es decir, este es un hilo viejo).

Si lo desea, puede ver los diferentes procesos por los que pasé (en una discusión sobre el #concrete5IRC) para que funcione a través de los diferentes pasos en este resumen: https://gist.github.com/3876924

El enfoque de patrón de complemento es mucho más limpio para admitir temporizadores individuales, etc.

Vea la publicación del blog para más.


17

Esto funcionó para mí:

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

1
Sin embargo, con el móvil, es extraño.
Radmation

El margen entre el menú y el menú desplegable hace que esto sea inútil.
antikbd

15

Esto está integrado en Bootstrap 3. Simplemente agregue esto a su CSS:

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

10

Aún mejor con jQuery:

jQuery('ul.nav li.dropdown').hover(function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).show();
  jQuery(this).addClass('open');
}, function() {
  jQuery(this).find('.dropdown-menu').stop(true, true).hide();
  jQuery(this).removeClass('open');
});

3
Cambié su código para jQuery('ul.nav li.dropdown').hover(function() { jQuery(this).closest('.dropdown-menu').stop(true, true).show(); jQuery(this).addClass('open'); }, function() { jQuery(this).closest('.dropdown-menu').stop(true, true).hide(); jQuery(this).removeClass('open'); });que el submenú no se muestre al pasar el mouse.
farjam

Este código ya no funcionará con las últimas versiones.
Paul

9

Puede usar el $().dropdown('toggle')método predeterminado para alternar el menú desplegable al pasar el mouse:

$(".nav .dropdown").hover(function() {
  $(this).find(".dropdown-toggle").dropdown("toggle");
});

9

Solo quiero agregar, que si tiene múltiples menús desplegables (como yo), debe escribir:

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

Y funcionará correctamente.


Mi .dropdown-menu tenía lo margin: 2px 0 0;que significaba que un mouse lento Enter desde arriba ocultaba el menú prematuramente. ul.dropdown-menu{ margin-top: 0; }
Alastair

8

En mi opinión, la mejor manera es la siguiente:

;(function($, window, undefined) {
    // 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 = $this.parent(),
                defaults = {
                    delay: 500,
                    instantlyCloseOthers: true
                },
                data = {
                    delay: $(this).data('delay'),
                    instantlyCloseOthers: $(this).data('close-others')
                },
                settings = $.extend(true, {}, defaults, options, data),
                timeout;

            $parent.hover(function(event) {

                // So a neighbor can't open the dropdown
                if(!$parent.hasClass('open') && !$this.is(event.target)) {
                    return true;
                }

                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

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

            // This helps with button groups!
            $this.hover(function() {
                if(settings.instantlyCloseOthers === true)
                    $allDropdowns.removeClass('open');

                window.clearTimeout(timeout);
                $parent.addClass('open');
            });

            // Handle submenus
            $parent.find('.dropdown-submenu').each(function(){
                var $this = $(this);
                var subTimeout;
                $this.hover(function() {
                    window.clearTimeout(subTimeout);
                    $this.children('.dropdown-menu').show();

                    // Always close submenu siblings instantly
                    $this.siblings().children('.dropdown-menu').hide();
                }, function() {
                    var $submenu = $this.children('.dropdown-menu');
                    subTimeout = window.setTimeout(function() {
                        $submenu.hide();
                    }, settings.delay);
                });
            });
        });
    };

    $(document).ready(function() {
        // apply dropdownHover to all elements with the data-hover="dropdown" attribute
        $('[data-hover="dropdown"]').dropdownHover();
    });
})(jQuery, this);

Marcado de muestra:

<li class="dropdown">
    <a href="#" class="dropdown-toggle" data-toggle="dropdown" data-hover="dropdown" data-delay="1000" data-close-others="false">
        Account <b class="caret"></b>
    </a>
    <ul class="dropdown-menu">
        <li><a tabindex="-1" href="#">My Account</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Change Email</a></li>
        <li><a tabindex="-1" href="#">Change Password</a></li>
        <li class="divider"></li>
        <li><a tabindex="-1" href="#">Logout</a></li>
    </ul>
</li>

55
Este es el trabajo de Cameron Spear, pensé en darle el saludo: cameronspear.com/blog/bootstrap-dropdown-on-hover-plugin
kelpie

8

La mejor manera de hacerlo es activar el evento de clic de Bootstrap con un cursor. De esta manera, debe seguir siendo compatible con dispositivos táctiles.

$('.dropdown').hover(function(){ 
  $('.dropdown-toggle', this).trigger('click'); 
});

Resultado no deseado: mousein, click y mouseout dejarán el menú abierto. Esto no es lo que quiero ...
Wietse

Usando esto, ejecuta la función bootstrap para abrir el menú desplegable, esa función hace muchas otras cosas, como aria-expanded = "true"
Farhad Sakhaei

7

Lo he logrado de la siguiente manera:

$('ul.nav li.dropdown').hover(function(){
       $(this).children('ul.dropdown-menu').slideDown(); 
    }, function(){
       $(this).children('ul.dropdown-menu').slideUp(); 
});

Espero que esto ayude a alguien...


5

También se agregó margin-top: 0 para restablecer el margen de arranque de CSS para .dropdown-menu para que la lista de menús no desaparezca cuando el usuario pasa lentamente del menú desplegable a la lista de menús.

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

.nav .dropdown-menu {
    margin-top: 0;
}

2
esta es la respuesta correcta, bootstrap está listo para pasar el mouse sobre el menú desplegable, si el mouse no sale del menú desplegable. Eliminar el margen superior permite ir del enlace al menú sin interrupción y, por lo tanto, sin cierre automático del menú. Y esta solución permite mantener el comportamiento correcto para los dispositivos táctiles
Nicolas Janel

5

Esta es probablemente una idea estúpida, pero para eliminar la flecha que apunta hacia abajo, puede eliminar el

<b class="caret"></b>

Sin embargo, esto no hace nada para el que apunta hacia arriba ...


5

He publicado un complemento adecuado para la funcionalidad de desplazamiento desplegable de Bootstrap 3, en el que incluso puedes definir qué sucede al hacer clic en eldropdown-toggle elemento (el clic se puede desactivar):

https://github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover


¿Por qué lo hice cuando ya hay muchas soluciones?

Tuve problemas con todas las soluciones existentes anteriormente. Los CSS simples no están usando la .openclase en el.dropdown , por lo que no habrá comentarios sobre el elemento de alternar desplegable cuando el desplegable sea visible.

Los js están interfiriendo al hacer clic en .dropdown-toggle , por lo que el menú desplegable aparece al pasar el mouse, luego lo oculta al hacer clic en un menú desplegable abierto, y al mover el mouse se activará el menú desplegable para que aparezca nuevamente. Algunas de las soluciones js están rompiendo la compatibilidad con iOS, algunos complementos no funcionan en los navegadores de escritorio modernos que admiten los eventos táctiles.

Es por eso que hice el complemento Bootstrap Dropdown Hover que evita todos estos problemas al usar solo la API estándar de Bootstrap javascript, sin ningún tipo de pirateo . Incluso los atributos de Aria funcionan bien con este complemento.


¿Cuál es su opinión sobre github.com/vadikom/smartmenus ? No puedo decidir, ambas bibliotecas parecen ser realmente buenas.
Csaba Toth

2
Smartmenus se ve muy bien, puede ser mejor para los menús. Mi complemento es solo una pequeña adición a los menús desplegables de bootstrap, no hace más que abrir un menú desplegable al pasar el mouse, mientras que smartmenu también admite submenús, y hace algunas otras cosas elegantes.
István Ujj-Mészáros

1
Gracias. Veo que el código de smartmenu es muy extenso y también hay mucho CSS. Hasta ahora fui con bootstrap-dropdown-hover, porque parece hacer el trabajo y más compacto. Estoy construyendo un sitio de aterrizaje con la barra de navegación del lado izquierdo.
Csaba Toth

4

Use este código para abrir el submenú en mousehover (solo escritorio):

$('ul.nav li.dropdown').hover(function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').show();
    }
}, function () {
    if ($(window).width() > 767) {
        $(this).find('.dropdown-menu').hide().css('display','');
    }
});

Y si desea que se pueda hacer clic en el menú del primer nivel, incluso en dispositivos móviles, agregue esto:

    $('.dropdown-toggle').click(function() {
    if ($(this).next('.dropdown-menu').is(':visible')) {
        window.location = $(this).attr('href');
    }
});

El submenú (menú desplegable) se abrirá con el mousehover en el escritorio y con clic / toque en el móvil y la tableta. Una vez que se abrió el submenú, un segundo clic le permitirá abrir el enlace. Gracias a if ($(window).width() > 767), el submenú ocupará el ancho de pantalla completa en el móvil.


Me gustaría usar su código, pero tengo problemas para que funcione correctamente. Primero, ¿cómo eliminar hover () para dispositivos móviles y usarlo solo para computadoras de escritorio? Cuando uso su código y cambio el tamaño de la ventana a móvil, obtengo la funcionalidad hover () y click (). Pero aún más extraño ... es que este comportamiento se detendrá Cuando actualice el navegador, ¡ja! ¿Podrías mostrarme cómo solucionar esto? Necesito submenús de escritorio para mostrar en hover () y hacer clic en () para mostrar submenús en dispositivos móviles sin tener que actualizar el navegador incluso cuando se cambia el tamaño de la ventana para que funcione correctamente. Espero que esto esté claro
Chris22

ok, eso tiene sentido e intentaré ejecutar tu solución de la manera que me recomiendas. ¡Gracias!
Chris22

Utilice este mejor método: @falter
Farhad Sakhaei


3

Esto ocultará los de arriba

.navbar .dropdown-menu:before {
   display:none;
}
.navbar .dropdown-menu:after {
   display:none;
}

3

Esto debería ocultar los menús desplegables y sus cuidados si son más pequeños que una tableta.

@media (max-width: 768px) {
    .navbar ul.dropdown-menu, .navbar li.dropdown b.caret {
        display: none;
    }
}

¿Por qué querrías ocultarlo? Ahora los usuarios de dispositivos móviles no tienen forma de acceder a los enlaces que se encuentran en el submenú. Es mejor desactivar el efecto de desplazamiento en un dispositivo móvil y mantener intacto el menú desplegable. De esa manera pueden abrirlo haciendo clic en él.
Paul

3

La solución jQuery es buena, pero tendrá que lidiar con los eventos al hacer clic (para dispositivos móviles o tabletas) ya que el desplazamiento no funcionará correctamente ... ¿Tal vez podría hacer alguna detección de cambio de tamaño de ventana?

La respuesta de Andres Ilich parece funcionar bien, pero debería incluirse en una consulta de medios:

@media (min-width: 980px) {

    .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;
    }
}

3

La solución muy simple para la versión 2, solo CSS. Mantiene la misma funcionalidad amigable para dispositivos móviles y tabletas.

@media (min-width: 980px) {
    .dropdown:hover .dropdown-menu {
       display: block;
    }
}

Esto no funciona muy bien para algunos temas donde hay una brecha entre el elemento del menú y el menú desplegable. El menú desaparecerá cuando el mouse se mueva a este espacio.
ndbroadbent

2

Sobrescriba bootstrap.js con este script.

jQuery(document).ready(function ($) {
$('.navbar .dropdown').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

$('.dropdown-submenu').hover(function() {
    $(this).addClass('extra-nav-class').find('.dropdown-menu').first().stop(true, true).delay(250).slideDown();
}, function() {
    var na = $(this)
    na.find('.dropdown-menu').first().stop(true, true).delay(100).slideUp('fast', function(){ na.removeClass('extra-nav-class') })
});

}); 

2

Aquí está mi técnica que agrega un ligero retraso antes de que el menú se cierre después de que dejas de desplazarte por el menú o el botón de alternar. Lo <button>que normalmente haría clic para mostrar el menú de navegación es #nav_dropdown.

$(function() {
  var delay_close_it, nav_menu_timeout, open_it;
  nav_menu_timeout = void 0;
  open_it = function() {
    if (nav_menu_timeout) {
      clearTimeout(nav_menu_timeout);
      nav_menu_timeout = null;
    }
    return $('.navbar .dropdown').addClass('open');
  };
  delay_close_it = function() {
    var close_it;
    close_it = function() {
      return $('.navbar .dropdown').removeClass('open');
    };
    return nav_menu_timeout = setTimeout(close_it, 500);
  };
  $('body').on('mouseover', '#nav_dropdown, #nav_dropdown *', open_it).on('mouseout', '#nav_dropdown', delay_close_it);
  return $('body').on('mouseover', '.navbar .dropdown .dropdown-menu', open_it).on('mouseout', '.navbar .dropdown .dropdown-menu', delay_close_it);
});

2

Para mejorar la respuesta de Sudharshan, envuelvo esto en una consulta de medios para evitar el desplazamiento cuando está en los anchos de pantalla XS ...

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

    .nav .dropdown-menu {
        margin-top: 0;
    }
}

Tampoco se requiere el cursor en el marcado, solo la clase desplegable para el li .


2

Esto funciona para WordPress Bootstrap:

.navbar .nav > li > .dropdown-menu:after,
.navbar .nav > li > .dropdown-menu:before {
    content: none;
}

2

Entonces tienes este código:

<a class="dropdown-toggle" data-toggle="dropdown">Show menu</a>

<ul class="dropdown-menu" role="menu">
    <li>Link 1</li>
    <li>Link 2</li> 
    <li>Link 3</li>                                             
</ul>

Normalmente funciona en un evento de clic y desea que funcione en un evento de desplazamiento. Esto es muy simple, solo use este código JavaScript / jQuery:

$(document).ready(function () {
    $('.dropdown-toggle').mouseover(function() {
        $('.dropdown-menu').show();
    })

    $('.dropdown-toggle').mouseout(function() {
        t = setTimeout(function() {
            $('.dropdown-menu').hide();
        }, 100);

        $('.dropdown-menu').on('mouseenter', function() {
            $('.dropdown-menu').show();
            clearTimeout(t);
        }).on('mouseleave', function() {
            $('.dropdown-menu').hide();
        })
    })
})

Esto funciona muy bien y aquí está la explicación: tenemos un botón y un menú. Cuando pasamos el botón, mostramos el menú, y cuando pasamos el mouse del botón, ocultamos el menú después de 100 ms. Si te preguntas por qué lo uso, es porque necesitas tiempo para arrastrar el cursor desde el botón sobre el menú. Cuando está en el menú, se restablece la hora y puede permanecer allí tantas veces como desee. Cuando salga del menú, ocultaremos el menú instantáneamente sin ningún tiempo de espera.

He usado este código en muchos proyectos, si encuentra algún problema al usarlo, no dude en hacerme preguntas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.