Home  >  Q&A  >  body text

How to detect click outside element?

<p>I have some HTML menus that I fully display when the user clicks on the header of these menus. I want to hide these elements when the user clicks outside the menu area. </p> <p>Is this possible using jQuery? </p> <pre class="brush:php;toolbar:false;">$("#menuscontainer").clickOutsideThisElement(function() { // Hide the menus });</pre> <p><br /></p>
P粉113938880P粉113938880395 days ago431

reply all(2)I'll reply

  • P粉212114661

    P粉2121146612023-08-24 12:19:34

    You can listen to the click event on document and then make sure that the #menucontainer is not an ancestor or target of the clicked element by using .closest().

    If not, the clicked element is outside the #menucontainer and you can safely hide it.

    $(document).click(function(event) { 
      var $target = $(event.target);
      if(!$target.closest('#menucontainer').length && 
      $('#menucontainer').is(":visible")) {
        $('#menucontainer').hide();
      }        
    });
    

    Edited – June 23, 2017

    You can also clean up after the event listener if you plan to close the menu and want to stop listening to events. This function will only clean up newly created listeners, leaving any other click listeners on document. Use ES2015 syntax:

    export function hideOnClickOutside(selector) {
      const outsideClickListener = (event) => {
        const $target = $(event.target);
        if (!$target.closest(selector).length && $(selector).is(':visible')) {
            $(selector).hide();
            removeClickListener();
        }
      }
    
      const removeClickListener = () => {
        document.removeEventListener('click', outsideClickListener);
      }
    
      document.addEventListener('click', outsideClickListener);
    }
    

    Edited – November 3, 2018

    For those who don't want to use jQuery. This is the plain vanillaJS (ECMAScript6) code above.

    function hideOnClickOutside(element) {
        const outsideClickListener = event => {
            if (!element.contains(event.target) && isVisible(element)) { // or use: event.target.closest(selector) === null
              element.style.display = 'none';
              removeClickListener();
            }
        }
    
        const removeClickListener = () => {
            document.removeEventListener('click', outsideClickListener);
        }
    
        document.addEventListener('click', outsideClickListener);
    }
    
    const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); // source (2018-03-11): https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js 
    

    Notice: This is based on Alex's comment, just use !element.contains(event.target) instead of the jQuery part.

    But element.closest() also now works in all major browsers (the W3C version is slightly different from the jQuery version). Polyfill can be found here: Element.closest()

    Edit – 2020-05-21

    If you want the user to be able to click and drag inside an element and then release the mouse outside the element without closing the element:

    ...
          let lastMouseDownX = 0;
          let lastMouseDownY = 0;
          let lastMouseDownWasOutside = false;
    
          const mouseDownListener = (event: MouseEvent) => {
            lastMouseDownX = event.offsetX;
            lastMouseDownY = event.offsetY;
            lastMouseDownWasOutside = !$(event.target).closest(element).length;
          }
          document.addEventListener('mousedown', mouseDownListener);

    In outsideClickListener:

    const outsideClickListener = event => {
            const deltaX = event.offsetX - lastMouseDownX;
            const deltaY = event.offsetY - lastMouseDownY;
            const distSq = (deltaX * deltaX) + (deltaY * deltaY);
            const isDrag = distSq > 3;
            const isDragException = isDrag && !lastMouseDownWasOutside;
    
            if (!element.contains(event.target) && isVisible(element) && !isDragException) { // or use: event.target.closest(selector) === null
              element.style.display = 'none';
              removeClickListener();
              document.removeEventListener('mousedown', mouseDownListener); // Or add this line to removeClickListener()
            }
        }

    reply
    0
  • P粉333186285

    P粉3331862852023-08-24 10:52:59

    Attach a click event to the document body of the closed window. Attach a separate click event to the container to stop propagation to the document body.

    $(window).click(function() {
      //Hide the menus if visible
    });
    
    $('#menucontainer').click(function(event){
      event.stopPropagation();
    });
    

    reply
    0
  • Cancelreply