Bulma dropdown doesn't seem to toggle on click. Below is the code snippet from the documentation:
<link href="" rel="stylesheet"/>
<div> <div> <button aria-haspopup="true" aria-controls="dropdown-menu"> <span>Dropdown button</span> <span> <i aria-hidden="true"></i> </span> </button> </div> <div> <div> <a href="#"> Dropdown item </a> <a> Other dropdown item </a> <a href="#"> Active dropdown item </a> <a href="#"> Other dropdown item </a> <hr> <a href="#"> With a divider </a> </div> </div>
</div> 2 4 Answers
You need to toggle the class is-active using JavaScript. When .dropdown has .is-active it changes the display of .dropdown-menu from none to block.
Here is a basic way to implement it.
var dropdown = document.querySelector('.dropdown');
dropdown.addEventListener('click', function(event) { event.stopPropagation(); dropdown.classList.toggle('is-active');
});<link href="" rel="stylesheet" />
<link rel="stylesheet" href="" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
<div> <div> <button aria-haspopup="true" aria-controls="dropdown-menu"> <span>Dropdown button</span> <span> <!--fontawesome required for the icon--> <i aria-hidden="true"></i> </span> </button> </div> <div> <div> <a href="#"> Dropdown item </a> <a> Other dropdown item </a> <a href="#"> Active dropdown item </a> <a href="#"> Other dropdown item </a> <hr> <a href="#"> With a divider </a> </div> </div>
</div> 7 Here's a full solution that has worked well for me using vanilla JS and making sure dropdowns close when you click out of them or press the Esc key.
// Get all dropdowns on the page that aren't hoverable.
const dropdowns = document.querySelectorAll('.dropdown:not(.is-hoverable)');
if (dropdowns.length > 0) { // For each dropdown, add event handler to open on click. dropdowns.forEach(function(el) { el.addEventListener('click', function(e) { e.stopPropagation(); el.classList.toggle('is-active'); }); }); // If user clicks outside dropdown, close it. document.addEventListener('click', function(e) { closeDropdowns(); });
}
/* * Close dropdowns by removing `is-active` class. */
function closeDropdowns() { dropdowns.forEach(function(el) { el.classList.remove('is-active'); });
}
// Close dropdowns if ESC pressed
document.addEventListener('keydown', function (event) { let e = event || window.event; if (e.key === 'Esc' || e.key === 'Escape') { closeDropdowns(); }
});<link href="" rel="stylesheet">
<link href="" rel="stylesheet">
<body>
<div> <div> <button aria-haspopup="true" aria-controls="dropdown-ui-actions"> <span>Actions</span> <span> <i aria-hidden="true"></i> </span> </button> </div> <div> <div> <a href="#"> Option 1 </a> <a href="#"> Option 2 </a> <a href="#"> Option 3 </a> </div> </div>
</div>
</body> 3 correction of te answer above: I added the closeDropdowns() function, because when we click in a second menu, both menus stay opened.
// Get all dropdowns on the page that aren't hoverable.
const dropdowns = document.querySelectorAll('.dropdown:not(.is-hoverable)');
if (dropdowns.length > 0) { // For each dropdown, add event handler to open on click. dropdowns.forEach(function(el) { el.addEventListener('click', function(e) { closeDropdowns(); e.stopPropagation(); el.classList.toggle('is-active'); }); }); // If user clicks outside dropdown, close it. document.addEventListener('click', function(e) { closeDropdowns(); });
}
/* * Close dropdowns by removing `is-active` class. */
function closeDropdowns() { dropdowns.forEach(function(el) { el.classList.remove('is-active'); });
}
// Close dropdowns if ESC pressed
document.addEventListener('keydown', function (event) { let e = event || window.event; if (e.key === 'Esc' || e.key === 'Escape') { closeDropdowns(); }
});<link href="" rel="stylesheet">
<link href="" rel="stylesheet">
<body>
<div> <div> <button aria-haspopup="true" aria-controls="dropdown-ui-actions"> <span>Actions</span> <span> <i aria-hidden="true"></i> </span> </button> </div> <div> <div> <a href="#"> Option 1 </a> <a href="#"> Option 2 </a> <a href="#"> Option 3 </a> </div> </div>
</div>
</body> I sniffed the javascript source listener on the docs page (I don't know why they don't make this more obvious tbh) and here it is for anyone else who may benefit.
Please note below I commented out a cookies aspect which I did not have defined and was throwing an error and seemed unimportant for my purposes.
"use strict";
document.addEventListener("DOMContentLoaded", function () { // Search var setSearchToggle = function setSearchToggle() { var icon = document.getElementById("searchIcon"); var search = document.getElementById("search"); var input = document.getElementById("algoliaSearch"); if (!icon) { return; } icon.addEventListener("click", function (event) { search.classList.toggle("bd-is-visible"); if (search.classList.contains("bd-is-visible")) { algoliaSearch.focus(); } }); window.addEventListener("keydown", function (event) { if (event.key === "Escape") { return search.classList.remove("bd-is-visible"); } }); }; setSearchToggle(); // Navbar var setNavbarVisibility = function setNavbarVisibility() { var navbar = document.getElementById("navbar"); if (!navbar) { return; } var cs = getComputedStyle(navbar); var paddingX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight); var brand = navbar.querySelector(".navbar-brand"); var end = navbar.querySelector(".navbar-end"); var search = navbar.querySelector(".bd-search"); var original = document.getElementById("navbarStartOriginal"); var clone = document.getElementById("navbarStartClone"); var rest = navbar.clientWidth - paddingX - brand.clientWidth - end.clientWidth - search.clientWidth; var space = original.clientWidth; var all = document.querySelectorAll("#navbarStartClone > .bd-navbar-item"); var base = document.querySelectorAll("#navbarStartClone > .bd-navbar-item-base"); var more = document.querySelectorAll("#navbarStartOriginal > .bd-navbar-item-more"); var dropdown = document.querySelectorAll("#navbarStartOriginal .bd-navbar-dropdown > .navbar-item"); var count = 0; var totalWidth = 0; var showMore = function showMore() {}; var hideMore = function hideMore() {}; var _iteratorNormalCompletion = true; var _didIteratorError = false; var _iteratorError = undefined; try { for (var _iterator = all[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { var item = _step.value; totalWidth += item.offsetWidth; if (totalWidth > rest) { break; } count++; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally { try { if (!_iteratorNormalCompletion && _iterator.return) { _iterator.return(); } } finally { if (_didIteratorError) { throw _iteratorError; } } } var howManyMore = Math.max(0, count - base.length); if (howManyMore > 0) { for (var i = 0; i < howManyMore; i++) { more[i].classList.add("bd-is-visible"); dropdown[i].classList.add("bd-is-hidden"); } } for (var j = howManyMore; j < more.length; j++) { more[j].classList.remove("bd-is-visible"); } for (var k = howManyMore; k < dropdown.length; k++) { dropdown[k].classList.remove("bd-is-hidden"); } }; setNavbarVisibility(); // Cookies
// var cookieBookModalName = "bulma_closed_book_modal";
// var cookieBookModal = Cookies.getJSON(cookieBookModalName) || false; // Dropdowns var $dropdowns = getAll(".dropdown:not(.is-hoverable)"); if ($dropdowns.length > 0) { $dropdowns.forEach(function ($el) { $el.addEventListener("click", function (event) { event.stopPropagation(); $el.classList.toggle("is-active"); }); }); document.addEventListener("click", function (event) { closeDropdowns(); }); } function closeDropdowns() { $dropdowns.forEach(function ($el) { $el.classList.remove("is-active"); }); } // Toggles var $burgers = getAll(".navbar-burger"); if ($burgers.length > 0) { $burgers.forEach(function ($el) { if (!$el.dataset.target) { return; } $el.addEventListener("click", function () { var target = $el.dataset.target; var $target = document.getElementById(target); $el.classList.toggle("is-active"); $target.classList.toggle("is-active"); }); }); } // Modals var rootEl = document.documentElement; var $modals = getAll(".modal"); var $modalButtons = getAll(".modal-button"); var $modalCloses = getAll(".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button"); if ($modalButtons.length > 0) { $modalButtons.forEach(function ($el) { $el.addEventListener("click", function () { var target = $el.dataset.target; openModal(target); }); }); } if ($modalCloses.length > 0) { $modalCloses.forEach(function ($el) { $el.addEventListener("click", function () { closeModals(); }); }); } function openModal(target) { var $target = document.getElementById(target); rootEl.classList.add("is-clipped"); $target.classList.add("is-active"); } function closeModals() { rootEl.classList.remove("is-clipped"); $modals.forEach(function ($el) { $el.classList.remove("is-active"); }); } document.addEventListener("keydown", function (event) { var e = event || window.event; if (e.keyCode === 27) { closeModals(); closeDropdowns(); } }); // Clipboard var $highlights = getAll(".highlight"); var itemsProcessed = 0; if ($highlights.length > 0) { $highlights.forEach(function ($el) { var copyEl = '<button>Copy</button>'; var expandEl = '<button>Expand</button>'; $el.insertAdjacentHTML("beforeend", copyEl); var $parent = $el.parentNode; if ($parent && $parent.classList.contains("bd-is-more")) { var showEl = '<button><span><i></i></span><strong>Show code</strong></button>'; $parent.insertAdjacentHTML("afterbegin", showEl); } else if ($el.firstElementChild.scrollHeight > 480 && $el.firstElementChild.clientHeight <= 480) { $el.insertAdjacentHTML("beforeend", expandEl); } itemsProcessed++; if (itemsProcessed === $highlights.length) { addHighlightControls(); } }); } function addHighlightControls() { var $highlightButtons = getAll(".highlight .bd-copy, .highlight .bd-expand"); $highlightButtons.forEach(function ($el) { $el.addEventListener("mouseenter", function () { $el.parentNode.classList.add("bd-is-hovering"); $el.parentNode.parentNode.classList.add("bd-is-hovering"); }); $el.addEventListener("mouseleave", function () { $el.parentNode.classList.remove("bd-is-hovering"); $el.parentNode.parentNode.classList.remove("bd-is-hovering"); }); }); var $highlightExpands = getAll(".bd-snippet .bd-expand"); $highlightExpands.forEach(function ($el) { $el.addEventListener("click", function () { $el.parentNode.firstElementChild.style.maxHeight = "none"; }); }); var $highlightShows = getAll(".bd-snippet .bd-show"); $highlightShows.forEach(function ($el) { $el.addEventListener("click", function () { var text = $el.querySelector("strong").textContent; var newText = text === "Show code" ? "Hide code" : "Show code"; $el.querySelector("strong").textContent = newText; $el.parentNode.classList.toggle("bd-is-more-clipped"); }); }); } setTimeout(function () { new Clipboard(".bd-copy", { target: function target(trigger) { return trigger.previousElementSibling.firstElementChild; } }); new Clipboard(".bd-clipboard"); }, 100); // Events var resizeTimer = void 0; function handleResize() { window.clearTimeout(resizeTimer); resizeTimer = window.setTimeout(function () { setNavbarVisibility(); }, 10); } window.addEventListener("resize", handleResize); // Utils function getAll(selector) { var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document; return Array.prototype.slice.call(parent.querySelectorAll(selector), 0); }
});