I am developing a simple dropdown menu with jQuery . When a user press on a trigger area, it will toggle the dropdown area. My question is how to have a click event outside of the dropdown menu so that it close the dropdown menu ?
7 Answers
You can tell any click that bubbles all the way up the DOM to hide the dropdown, and any click that makes it to the parent of the dropdown to stop bubbling.
/* Anything that gets to the document
will hide the dropdown */
$(document).click(function(){
$("#dropdown").hide();
});
/* Clicks within the dropdown won't make
it past the dropdown itself */
$("#dropdown").click(function(e){
e.stopPropagation();
});

- 265,109
- 74
- 539
- 565
-
15If there are other elements on the page that have click handlers they could prevent the click event from bubbling down to the document. – jacob.toye Jun 24 '11 at 05:04
-
@jacob.toy Only if they are stopping propagation would they prevent it. – Sampson Jun 24 '11 at 05:08
-
So, is this why this solutions works well? Due to your comments, @JonathanSampson and @jacob.toye? – Con Antonakos Jan 21 '14 at 23:36
-
9This doesn't work if you have two dropdowns as you'll be stopping the event from triggering up to the document. – opsb Jun 28 '14 at 02:17
-
2This solution is not universal. It actually blocks the dropdown from showing in some cases. – Patrick Mutuku Nov 20 '18 at 11:38
how to have a click event outside of the dropdown menu so that it close the dropdown menu ? Heres the code
$(document).click(function (e) {
e.stopPropagation();
var container = $(".dropDown");
//check if the clicked area is dropDown or not
if (container.has(e.target).length === 0) {
$('.subMenu').hide();
}
})

- 381
- 3
- 10
-
My favorite solution of the bunch because it allows for events on child elements to propagate properly. – NolanDC Aug 08 '13 at 22:38
-
Nice! This works really well. So, essentially, this line of logic, `container.has(e.target).length === 0`, checks if the event target is a `$('.dropDown')`, and if not, hide the `subMenu`? – Con Antonakos Jun 14 '15 at 20:39
-
The best solution, but `e.stopPropagation();` doesn't really make sense because `document` is already one of the highest (last) levels in the DOM – clarkk Aug 27 '22 at 06:08
Stopping Event Propagation in some particular elements ma y become dangerous as it may prevent other some scripts from running. So check whether the triggering is from the excluded area from inside the function.
$(document).on('click', function(event) {
if (!$(event.target).closest('#menucontainer').length) {
// Hide the menus.
}
});
Here function is initiated when clicking on document, but it excludes triggering from #menucontainer. For details https://css-tricks.com/dangers-stopping-event-propagation/

- 1,099
- 10
- 13
-
1
-
To use `if (container.has(e.target).length === 0)` is much better performance... – clarkk Aug 27 '22 at 06:10
You would need to attach your click event to some element. If there are lots of other elements on the page you would not want to attach a click event to all of them.
One potential way would be to create a transparent div below your dropdown menu but above all other elements on the page. You would show it when the drop down was shown. Have the element have a click hander that hides the drop down and the transparent div.
$('#clickCatcher').click(function () {
$('#dropContainer').hide();
$(this).hide();
});
#dropContainer { z-index: 101; ... }
#clickCatcher { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 100; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dropDown"></div>
<div id="clickCatcher"></div>

- 4,195
- 12
- 39
- 49

- 1,212
- 11
- 14
-
+1 Neat method. Definitely worth giving a shot. It's worth noting that you don't need to attach click events to all other elements though; a single handler at the document level would be sufficient in most cases. – Sampson Jun 24 '11 at 05:10
Another multiple dropdown example that works https://jsfiddle.net/vgjddv6u/
$('.moderate .button').on('click', (event) => {
$(event.target).siblings('.dropdown')
.toggleClass('is-open');
});
$(document).click(function(e) {
$('.moderate')
.not($('.moderate').has($(e.target)))
.children('.dropdown')
.removeClass('is-open');
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.0/css/bulma.css" rel="stylesheet" />
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<style>
.dropdown {
box-shadow: 0 0 2px #777;
display: none;
left: 0;
position: absolute;
padding: 2px;
z-index: 10;
}
.dropdown a {
font-size: 12px;
padding: 4px;
}
.dropdown.is-open {
display: block;
}
</style>
<div class="control moderate">
<button class="button is-small" type="button">
moderate
</button>
<div class="box dropdown">
<ul>
<li><a class="nav-item">edit</a></li>
<li><a class="nav-item">delete</a></li>
<li><a class="nav-item">block user</a> </li>
</ul>
</div>
</div>
<div class="control moderate">
<button class="button is-small" type="button">
moderate
</button>
<div class="box dropdown">
<ul>
<li><a class="nav-item">edit</a></li>
<li><a class="nav-item">delete</a></li>
<li><a class="nav-item">block user</a></li>
</ul>
</div>
</div>

- 379
- 5
- 8
Selected answer works for one drop down menu only. For multiple solution would be:
$('body').click(function(event){
$dropdowns.not($dropdowns.has(event.target)).hide();
});

- 9,266
- 3
- 25
- 28
There is a tricky way to do this. You can manipulate blur
event by adding tabIndex
.
$('.click').click(function (e) {
$(this).siblings('.dropdown').fadeToggle(100);
});
$('.container').blur(function (e) {
$('.dropdown').fadeOut(100);
});
.container{
position: relative;
display: inline-block;
}
.click{
cursor: pointer;
user-select: none;
z-index: 1;
}
.dropdown{
position: absolute;
left: 0;
top: 100%;
display: none;
background: #eee;
padding: 1rem;
z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="container" tabIndex="1">
<section class="click">click this</section>
<section class="dropdown">
dropdown menu here
</section>
</section>
<br /> <br />
<section class="container" tabIndex="2">
<section class="click">click this</section>
<section class="dropdown">
dropdown menu here
</section>
</section>

- 169
- 2
- 12