Hice un menú desplegable en mi encabezado, y cuando hago clic en el ícono de la luna (en la parte superior derecha), la lista desplegable no aparece, pero se llama a la función cuando hago clic en el ícono. Intenté usar botones pero luego hacer clic en el icono no funciona. ¿Alguien me ayuda con esto? soy nuevo en esto gracias.
HTML:
<li> <div class="dropdown"> <script src="./assets/js/Dropdown.js"></script> <i class="fa-solid fa-bolt fa-lg" class="dropbtn" onclick="Dropdown()"></i> <div id="myDropdown" class="dropdown-content"> <a><i class="fa-solid fa-moon"></i> Dark Mode</a> <a><i class="fa-solid fa-sun"></i> Light Mode</a> <a><i class="fa-solid fa-display"></i> System</a> </div> </div> </li>CSS:
.dropbtn { background-color: #24252A; color: white; padding: 16px; font-size: 16px; border: none; cursor: pointer; } .dropdown { position: relative; display: inline-block; } .dropdown-content { display: none; position: absolute; background-color: #f1f1f1; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); z-index: 1; cursor: pointer; } .dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block; } .dropdown-content a:hover { background-color: #ddd; } .show { display: block; }JavaScript:
function Dropdown() { document.getElementById("myDropdown").classList.toggle("show"); } window.onclick = function(event) { if (!event.target.matches('.dropbtn')) { var dropdowns = document.getElementsByClassName("dropdown-content"); var i; for (i = 0; i < dropdowns.length; i++) { var openDropdown = dropdowns[i]; if (openDropdown.classList.contains('show')) { openDropdown.classList.remove('show'); } } } }Yo solía tener ese problema. Pero no tienes que reinventar la rueda, te recomiendo usar un framework CSS, como Materialise o Bootstrap .
Recomiendo Materialise, es fácil de usar y solo tienes que inicializar cada elemento que quieras usar.
Te muestro un ejemplo de barra de navegación:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Example</title> <!-- Google icons --> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css"> </head> <body> <nav> <div class="nav-wrapper"> <a href="#!" class="brand-logo">Logo</a> <a href="#" data-target="mobile-demo" class="sidenav-trigger"><i class="material-icons">menu</i></a> <ul class="right hide-on-med-and-down"> <li><a href="sass.html">Sass</a></li> <li><a href="badges.html">Components</a></li> <li><a href="collapsible.html">Javascript</a></li> <li><a href="mobile.html">Mobile</a></li> </ul> </div> </nav> <ul class="sidenav" id="mobile-demo"> <li><a href="sass.html">Sass</a></li> <li><a href="badges.html">Components</a></li> <li><a href="collapsible.html">Javascript</a></li> <li><a href="mobile.html">Mobile</a></li> </ul> <!-- Compiled and minified JavaScript --> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> <!-- Materialize initializers --> <script> document.addEventListener('DOMContentLoaded', function() { var elems = document.querySelectorAll('.sidenav'); var instances = M.Sidenav.init(elems); });</script> </body> </html>Tiene dos atributos de clase en su elemento de icono.
Cuando el usuario hace clic en el ícono, hay dos eventos de clic: el primero ocurre en el ícono mismo y la clase de presentación se agrega correctamente.
El segundo es el clic general en la ventana. Tener dos clases confunde la función de coincidencias de JS que considera que el elemento no coincide (es decir, no se seleccionaría con .dropbtn) [probablemente no sea exactamente 'confundido', solo mira el atributo de primera clase, por lo que pierde el valor de dropbtn] por lo que borra el Mostrar clase.
Si coloca todas las clases del ícono en un valor de atributo, entonces todo funciona bien.
function Dropdown() { document.getElementById("myDropdown").classList.toggle("show"); } window.onclick = function(event) { if (!event.target.matches('.dropbtn')) { var dropdowns = document.getElementsByClassName("dropdown-content"); var i; for (i = 0; i < dropdowns.length; i++) { var openDropdown = dropdowns[i]; if (openDropdown.classList.contains('show')) { openDropdown.classList.remove('show'); } } } } .dropbtn { background-color: #24252A; color: white; padding: 16px; font-size: 16px; border: none; cursor: pointer; } .dropdown { position: relative; display: inline-block; } .dropdown-content { display: none; position: absolute; background-color: #f1f1f1; min-width: 160px; box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); z-index: 1; cursor: pointer; } .dropdown-content a { color: black; padding: 12px 16px; text-decoration: none; display: block; } .dropdown-content a:hover { background-color: #ddd; } .show { display: block; } <li> <div class="dropdown"> <script src="./assets/js/Dropdown.js"></script> <i class="fa-solid fa-bolt fa-lg dropbtn" onclick="Dropdown()">click me</i> <div id="myDropdown" class="dropdown-content"> <a><i class="fa-solid fa-moon"></i> Dark Mode</a> <a><i class="fa-solid fa-sun"></i> Light Mode</a> <a><i class="fa-solid fa-display"></i> System</a> </div> </div> </li>En su lugar, podría considerar usar event.stopPropagation en el primer controlador de eventos, lo que detendría el evento de clic en toda la ventana.