Detecting a click outside an element in JavaScript is a very common pattern that can be used to close a non modal user interface component like a flyout, a menu or a dropdown when the user clicks outside this element. While searching on the web there are a lot of various jQuery solutions but I wanted to implement a vanilla JavaScript solution so I could easily copy and paste it later in my projects.

Example for a flyout

For this article I’m going to detect a click outside a flyout, popover or dropdown element like this one:

The flyout in HTML

<div class="flyout" id="flyout-example">  
    <h5 class="flyout-title">This could be a flyout&hellip;</h5>
    <div class="flyout-debug" id="flyout-debug"></div>
    <div class="flyout-buttons">
        <button class="button button-outline" type="button">Cancel</button>
        <button class="button" type="button">Ok</button>
    </div>
</div>  

JavaScript ES6 code

To detect a click outside an element we must add a listener on the whole document element. Then the main loop goes up the DOM from the clicked target element to find whether an ancestor of the clicked element belongs to the flyout container.

This is the JavaScript code with the fancy ES6 features:

document.addEventListener("click", (evt) => {  
    const flyoutElement = document.getElementById("flyout-example");
    let targetElement = evt.target; // clicked element

    do {
        if (targetElement == flyoutElement) {
            // This is a click inside. Do nothing, just return.
            document.getElementById("flyout-debug").textContent = "Clicked inside!";
            return;
        }
        // Go up the DOM
        targetElement = targetElement.parentNode;
    } while (targetElement);

    // This is a click outside.
    document.getElementById("flyout-debug").textContent = "Clicked outside!";
});

Older versions of JavaScript

The ES6 code runs in modern browsers. If we want it to run on older browsers we can adapt the code or transpile it with a tool like Babel even available as an online converter.

This is the adapted JavaScript code:

document.addEventListener("click", function(evt) {  
    var flyoutElement = document.getElementById('flyout-example'),
        targetElement = evt.target;  // clicked element

    do {
        if (targetElement == flyoutElement) {
            // This is a click inside. Do nothing, just return.
            document.getElementById("flyout-debug").textContent = "Clicked inside!";
            return;
        }
        // Go up the DOM
        targetElement = targetElement.parentNode;
    } while (targetElement);

    // This is a click outside.
    document.getElementById("flyout-debug").textContent = "Clicked outside!";
});

Demo

A small demo displaying whether a click is detected inside or outside a flyout element.

See the Pen Detecting a Click Outside an Element in JavaScript by Frederic Perrin (@blustemy) on CodePen.