Menú desplegable de Twitter Bootstrap multinivel

Respuestas:

113

Respuesta actualizada

* Respuesta actualizada que admite la hoja de estilo de la versión de arranque v2.1.1 **.

** Pero tenga cuidado porque esta solución se ha eliminado de la v3

Solo quería señalar que esta solución ya no es necesaria, ya que el último bootstrap ahora admite menús desplegables de varios niveles de forma predeterminada. Aún puede usarlo si tiene versiones anteriores, pero para aquellos que actualizaron a la última versión (v2.1.1 en el momento de escribir este artículo) ya no es necesario. Aquí hay un violín con el menú desplegable predeterminado de varios niveles actualizado directamente de la documentación:

http://jsfiddle.net/2Smgv/2858/


Respuesta original

Se han planteado algunos problemas en el soporte de submenús en github y, por lo general, los desarrolladores de bootstrap los cierran, como este , por lo que creo que los desarrolladores usan el bootstrap para resolver algo. Aquí hay una demostración que armé que le muestra cómo puede piratear un submenú funcional.

Código relevante

CSS

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

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

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

Creé mi propia .sub-menuclase para aplicarla a los menús desplegables de 2 niveles, de esta manera podemos colocarlos junto a los elementos de nuestro menú. También modificó la flecha para mostrarla a la izquierda del grupo de submenús.

Manifestación

Andrés Ilich
fuente
2
A partir de Bootstrap 2.0.4, también debe tener la declaración "display: block;" en el selector ".dropdown-menu li: hover .sub-menu".
Omar
Traté de implementarlo, el primer submenú funciona bien. Pero si agrego otro submenú en el mismo menú, entonces las cosas salen mal. Por alguna razón, abre el primer submenú en lugar del segundo. Cualquier idea o pista será bienvenida. Ya gracias :)
Arjan
Hermes: vea mi respuesta sobre cómo solucionar el problema del submenú.
Sean Lynch
1
@Kannika movilizar esta solución requeriría un marcado adicional y probablemente también algo de javascript. Sugiero mostrar el contenido del menú desplegable de segundo nivel en lugar de ocultarlo en dispositivos móviles para mantener las cosas limpias. Intentaré trabajar en una solución más tarde durante el día. Sin embargo, no he probado la solución de arranque predeterminada, por lo que, en todo caso, siempre puede ir con eso.
Andrés Ilich
5
La versión actualizada solo funciona con Bootstrap 2.3.2, se eliminó en Bootstrap 3.0
seantomburke
34

[Twitter Bootstrap v3]

Para crear un menú desplegable de n niveles (compatible con dispositivos táctiles) en Twitter Bootstrap v3,

CSS:

.dropdown-menu>li /* To prevent selection of text */
{   position:relative;
    -webkit-user-select: none; /* Chrome/Safari */        
    -moz-user-select: none; /* Firefox */
    -ms-user-select: none; /* IE10+ */
    /* Rules below not implemented in browsers yet */
    -o-user-select: none;
    user-select: none;
    cursor:pointer;
}
.dropdown-menu .sub-menu 
{
    left: 100%;
    position: absolute;
    top: 0;
    display:none;
    margin-top: -1px;
    border-top-left-radius:0;
    border-bottom-left-radius:0;
    border-left-color:#fff;
    box-shadow:none;
}
.right-caret:after,.left-caret:after
 {  content:"";
    border-bottom: 5px solid transparent;
    border-top: 5px solid transparent;
    display: inline-block;
    height: 0;
    vertical-align: middle;
    width: 0;
    margin-left:5px;
}
.right-caret:after
{   border-left: 5px solid #ffaf46;
}
.left-caret:after
{   border-right: 5px solid #ffaf46;
}

JQuery:

$(function(){
    $(".dropdown-menu > li > a.trigger").on("click",function(e){
        var current=$(this).next();
        var grandparent=$(this).parent().parent();
        if($(this).hasClass('left-caret')||$(this).hasClass('right-caret'))
            $(this).toggleClass('right-caret left-caret');
        grandparent.find('.left-caret').not(this).toggleClass('right-caret left-caret');
        grandparent.find(".sub-menu:visible").not(current).hide();
        current.toggle();
        e.stopPropagation();
    });
    $(".dropdown-menu > li > a:not(.trigger)").on("click",function(){
        var root=$(this).closest('.dropdown');
        root.find('.left-caret').toggleClass('right-caret left-caret');
        root.find('.sub-menu:visible').hide();
    });
});

HTML:

<div class="dropdown" style="position:relative">
    <a href="#" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">Click Here <span class="caret"></span></a>
    <ul class="dropdown-menu">
        <li>
            <a class="trigger right-caret">Level 1</a>
            <ul class="dropdown-menu sub-menu">
                <li><a href="#">Level 2</a></li>
                <li>
                    <a class="trigger right-caret">Level 2</a>
                    <ul class="dropdown-menu sub-menu">
                        <li><a href="#">Level 3</a></li>
                        <li><a href="#">Level 3</a></li>
                        <li>
                            <a class="trigger right-caret">Level 3</a>
                            <ul class="dropdown-menu sub-menu">
                                <li><a href="#">Level 4</a></li>
                                <li><a href="#">Level 4</a></li>
                                <li><a href="#">Level 4</a></li>
                            </ul>
                        </li>
                    </ul>
                </li>
                <li><a href="#">Level 2</a></li>
            </ul>
        </li>
        <li><a href="#">Level 1</a></li>
        <li><a href="#">Level 1</a></li>
    </ul>
</div>
Chirayu Chiripal
fuente
Desafortunadamente, esto no muestra el menú cuando se muestra el botón 'contraído' del menú. En Chrome y en FF.
Ben Power
@BenPower ¿Puede proporcionar una demostración de jsfiddle para que pueda investigarlo porque la demostración de jsfiddle que he dado está funcionando bien? Además, ¿qué versiones de Bootstrap, JQuery y navegadores web está utilizando?
Chirayu Chiripal
Funciona para Bootstrap v3.0. Amigo ... ¿Podrías hacer que sea compatible con Bootstrap v2.3.2?
Niks Jain
1
Agregué trigger.off('click');antes de configurar los oyentes para evitar la "doble escucha" de un evento en caso de que la inicialización de JavaScript se active más de una vez.
FranBran
1
Invertir el signo de intercalación agregó varias líneas de código y es innecesario.
Ruben
23

Este ejemplo es de http://bootsnipp.com/snippets/featured/multi-level-dropdown-menu-bs3

Funciona para mí en Bootstrap v3.1.1.

HTML

<div class="container">
<div class="row">
    <h2>Multi level dropdown menu in Bootstrap 3</h2>
    <hr>
    <div class="dropdown">
        <a id="dLabel" role="button" data-toggle="dropdown" class="btn btn-primary" data-target="#" href="/page.html">
            Dropdown <span class="caret"></span>
        </a>
        <ul class="dropdown-menu multi-level" role="menu" aria-labelledby="dropdownMenu">
          <li><a href="#">Some action</a></li>
          <li><a href="#">Some other action</a></li>
          <li class="divider"></li>
          <li class="dropdown-submenu">
            <a tabindex="-1" href="#">Hover me for more options</a>
            <ul class="dropdown-menu">
              <li><a tabindex="-1" href="#">Second level</a></li>
              <li class="dropdown-submenu">
                <a href="#">Even More..</a>
                <ul class="dropdown-menu">
                    <li><a href="#">3rd level</a></li>
                    <li><a href="#">3rd level</a></li>
                </ul>
              </li>
              <li><a href="#">Second level</a></li>
              <li><a href="#">Second level</a></li>
            </ul>
          </li>
        </ul>
    </div>
</div>

CSS

.dropdown-submenu {
position: relative;
}

.dropdown-submenu>.dropdown-menu {
top: 0;
left: 100%;
margin-top: -6px;
margin-left: -1px;
-webkit-border-radius: 0 6px 6px 6px;
-moz-border-radius: 0 6px 6px;
border-radius: 0 6px 6px 6px;
}

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

.dropdown-submenu>a:after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 5px 0 5px 5px;
border-left-color: #ccc;
margin-top: 5px;
margin-right: -10px;
}

.dropdown-submenu:hover>a:after {
border-left-color: #fff;
}

.dropdown-submenu.pull-left {
float: none;
}

.dropdown-submenu.pull-left>.dropdown-menu {
left: -100%;
margin-left: 10px;
-webkit-border-radius: 6px 0 6px 6px;
-moz-border-radius: 6px 0 6px 6px;
border-radius: 6px 0 6px 6px;
}
fandasson
fuente
Gracias ! la versión 3.0 ya no admite la respuesta validada
Asenar
13

Pude arreglar que el submenú siempre se fijara en la parte superior del menú principal de la respuesta de Andrés con la siguiente adición:

.dropdown-menu li {
    position: relative;
}

También agrego un ícono "icon-chevron-right" en los elementos que contienen submenús de menú, y cambio el ícono de negro a blanco al pasar el mouse (para complementar el cambio de texto a blanco y verse mejor con el fondo azul seleccionado).

Aquí está el cambio completo de less / css (reemplace lo anterior con esto):

.dropdown-menu li {
    position: relative;

    [class^="icon-"] {
        float: right;
    }

    &:hover {
        // Switch to white icons on hover
        [class^="icon-"] {
            background-image: url("../img/glyphicons-halflings-white.png");
        }
    }
}
Sean Lynch
fuente
4

Acabo de agregar class="span2"a los <li>elementos del menú desplegable y funcionó.

P.EJ
fuente
3

Dado que Bootstrap 3 eliminó la parte del submenú y necesitamos adaptarnos el estilo, creo que es mejor ir con SmartMenu Bootstrap: https://vadikom.github.io/smartmenus/src/demo/bootstrap-navbar.html#

Eso nos ahorraría tiempo en el estilo y la respuesta móvil.

Este complemento también es muy prometedor.

Osify
fuente
¿Cuál es tu opinión sobre github.com/istvan-ujjmeszaros/bootstrap-dropdown-hover ? No puedo decidir.
Csaba Toth
1
@CsabaToth, este también estaba en mi consideración, si desea tener solo la API de javascript de arranque, puede optar por este, lo suficientemente ligero como para agregarlo y puede estar familiarizado con la habilidad general de arranque si necesita personalizarlo.
Osify
Finalmente, usaré uno de ellos en un proyecto y el otro en un sitio complementario. Cada solución se adapta mejor a una de ellas
Csaba Toth