Often JavaScript developers need to work with user clicks. Typically, they need to trigger events when user clicks on specific HTML elements. But sometimes, then may also need to detect click outside element in JavaScript. In this article, we will learn how to listen for click outside element in JavaScript. You can use it to detect click outside div, lists, menus and other HTML elements.
The Problem
Generally, web developers need to add event handlers for HTML elements to detect clicks inside them. This is easy and there are many readymade functions for this purpose. But sometimes, you may need to process clicks made outside an element. Unfortunately, there is no direct solution to this use case.
But it can be solved by understanding that events can be attached to any element on a web page, even parent elements or elements outside the said element. Basically, when a user makes a click, you need to check if the click target is outside your element, or if it is the parent element. If that is the case, then the click has occurred outside the element.
How to Detect Click Outside Element in JavaScript
There are several ways to detect click outside element in JavaScript. Some use jQuery library while some use plain JavaScript. We will look at both of them one by one. Let us say you have the following HTML dropdown menu along with its CSS.
<div id="menu_wrap">
<a href="#" id="menu_toggle">Menu Toggle</a>
<ul id="menu_container">
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
</ul>
</div>
#menu_container {
display:none;
}
The above CSS will hide the menu options by default. Let us say you want to expand the menu when user clicks on the menu head, and collapse the menu when user clicks outside the menu. For this purpose, let us say you have the following jQuery function to toggle the menu when user clicks the menu head.
$('#menu_toggle').click(function(event){
$('#menu_container').toggle();
});
1. Using event.stopPropagation()
We will be using jQuery to easily implement this solution. First of all, we will add a click event handler to the parent or any of the ancestor elements of this menu. It is typically, document, body, or html, since these elements contain all page elements. This click event handler will simply hide the menu on click.
$('html').click(function() {
$('#menu_container').hide();
});
But this is not enough. When a user clicks any part of html tag, this click will be propagated to all child elements on the page. So we need to stop this click from reaching our menu which is also inside the html tag. Otherwise, it will also trigger the toggle() function we assigned to its event handler earlier. For this purpose, we will add the following code.
$('#menu_wrap').click(function(event){
event.stopPropagation();
});
Now the menu will hide when user clicks anywhere outside it. It will also toggle when user clicks on the menu itself.
2. Using event.composedPath()
Some web developers may not prefer the above method since it used stopPropagation() to prevent the click from traversing further down the HTML DOM tree. Most modern web browsers also support a function composedPath() for each event. When called, it returns an array of all objects on page, on which the event’s listeners will be called. Here is its syntax.
even.composedPath()
To use the above code, we first select the target element, that is menu, outside which we are detecting clicks.
var target = document.querySelector('#menu_wrap');
Next, we add a click handler to the document object on web page.
document.addEventListener('click', (event) => {
var withinBoundaries = event.composedPath().includes(target)
if (withinBoundaries) {
//do nothing since click is inside menu
} else {
$('#menu_container').hide();
}
})
The above handler checks if the click target is same as our menu. For this purpose, we use event.composedPath().includes() function. If that is the case, it does nothing, else it will hide the menu.
3. Using closest() function
You can also attach a click handler to document element and ensure that our menu is not an ancestor of the clicked element, using closest() function. closest() function basically starts from the target element and traverses up the node tree thorough its ancestors, checking whether our menus is one of them.
$(document).click(function(event) {
var $target = $(event.target);
if(!$target.closest('#menu_container').length &&
$('#menu_container').is(":visible")) {
$('#menu_container').hide();
}
});
$('#menu_wrap').click(function(event){
event.stopPropagation();
});
Here also, we need to disable click propagation to the menu, when any element in HTML document is clicked.
3. Using jQuery blur
Every element triggers a blur event when user clicks outside the element. You can use its event handler to simply hide the menu.
$("#menu_toggle").blur(function(){
$('#menu_container').hide();
});
4. Using focusout
Similarly, you can also use focusout event handler, which is called, when the mouse focuses out of an element.
$("#menu_toggle").focusout(function(){
$('#menu_container').hide();
});
5. Using event.target
Another simple solution is to just check if the clicked element is the target element or not. If it is not the target element then it means the click was outside the element.
$(document).click(function(event) {
if(!$(event.target).is('#menu_toggle'))
{
$('#menu_container').hide();
}
});
In the above code, we add a click handler to document object. In it, we check if the event.target is the menu or not. If it is not menu, then the click outside the menu and we hide the menu.
6. Using target.id
Similarly, you can also check the ID attribute of the clicked element to determine if it is the same as that of the menu. If that is not the case, then it means the click was done outside the element.
$(document).click(function (e) {
if (e.target.id != 'menu_toggle') {
$('#menu_container').hide();
}
});
In the above code, we add a click handler to document object. In it, we check if the click target’s id is ‘menu_toggle’ that is the menu’s ID. If that is not the case, then we hide the menu, since the click was made outside the element.
7. Using Plain JavaScript
Many websites do not use jQuery. In such cases, you can use plain JavaScript to solve this problem. Here is the previous solution using plain JavaScript.
document.addEventListener('click', function (e) {
if (e.target.id != 'menu_toggle') {
document.getElementById('menu_container').style.display='none';
}
});
In the above code, we use addEventListener() to add an event handler to document object. We check the ID attribute of click target. If it is not menu_toggle, then we set the display CSS property of menu_container element to none, which basically hides it.
Conclusion
In this article, we have learnt how to detect click outside element in JavaScript. Although, we have implemented it for a dropdown menu, it can be used for other HTML elements such as div, button, paragraphs, etc. because we are working with the ID CSS selector of the element. So it can be applied to any HTML element. We have learnt many different ways to solve this problem, along with their pros and cons. You can use any of these methods depending on your requirement. Please note, in most cases we have used a combination of JavaScript and jQuery since it is the easiest. For example, we have used plain JavaScript functions such as closest(), stopPropagation(), composedPath() and jQuery functions like toggle(), hide(). You can mix and match as per your requirement.
FAQs
1. Can we use these solutions with any HTML element?
Yes. Since we are using the ID attribute of HTML menus in above example, you can use this attribute for any element. You may need to adjust the ID attribute that is being hidden on user click. For our example, we detect clicks outside menu element with ID=menu_toggle and hide the element with ID=menu_container. If you are using it on a div then both these IDs will be the ID of your div.
2. Do I need to use jQuery to solve this problem?
No. You can also solve this problem using plain JavaScript. But it has a complicated syntax. If you use any other third-party JS library such as AngularJS, you can also it for this purpose. We have used plain JavaScript functions like closest(), composedPath() as well as jQuery functions like toggle().
Also read:
How to Know Which Radio Button is Selected in jQuery
How JavaScript Closures Work
How to Check Whether String Contains Substring in JavaScript
Sreeram Sreenivasan is the Founder of Ubiq. He has helped many Fortune 500 companies in the areas of BI & software development.