Search code examples
javascript

Close menu when click outside DIV


I need to close menu when clicked outside div on mobile view or when browser is resized.

See screenshot here

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
  <title>Admin Dashboard | Keyframe Effects</title>
  <link rel="stylesheet" href="style.css">
  <link rel="stylesheet" href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css">
</head>
Style section

<style>
  @import url('https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@300;400;500;600&display=swap');
  :root {
    --main-color: #34425A;
    --color-dark: #34425A;
    --text-grey: #B0B0B0;
  }
  
  * {
    margin: 0;
    padding: 0;
    text-decoration: none;
    list-style-type: none;
    box-sizing: border-box;
    font-family: 'Merriweather', sans-serif;
  }
  
  #menu-toggle {
    display: none;
  }
  
  .sidebar {
    position: fixed;
    height: 100%;
    width: 165px;
    left: 0;
    bottom: 0;
    top: 0;
    z-index: 100;
    background-color: #d6eaf8;
    transition: left 300ms;
  }
  
  .side-menu ul li:hover {
    background-color: #1b4f72;
  }
  
  .side-menu a {
    color: #555;
    font-size: 1rem;
  }
  
  .side-menu a:hover {
    color: #fff;
    /* Change menu hover text color here */
  }
  
  .side-header {
    background-color: #2471a3;
    height: 60px;
    display: flex;
    justify-content: center;
    align-items: center;
  }
  
  .side-header h3,
  side-head span {
    color: #fff;
    font-weight: 400;
  }
  
  .side-content {
    padding: 2rem 0rem;
    height: calc(100vh - 60px);
    overflow: auto;
  }
  /* width */
  
  .side-content::-webkit-scrollbar {
    width: 5px;
  }
  /* Track */
  
  .side-content::-webkit-scrollbar-track {
    box-shadow: inset 0 0 5px grey;
    border-radius: 10px;
  }
  /* Handle */
  
  .side-content::-webkit-scrollbar-thumb {
    background: #b0b0b0;
    border-radius: 10px;
  }
  /* Handle on hover */
  
  .side-content::-webkit-scrollbar-thumb:hover {
    background: #b30000;
  }
  
  .sidebar {
    /*overflow-y: auto;*/
  }
  
  .side-menu ul {
    text-align: center;
  }
  
  .side-menu a {
    display: block;
    padding: 1rem 0rem;
    text-align: left;
  }
  
  .side-menu a.active {
    background: #1b4f72;
    border-bottom: solid 1px #d6eaf8;
  }
  
  .side-menu a.active span,
  .side-menu a.active small {
    color: #fff;
  }
  
  .side-menu a span {
    min-height: 15px;
    display: inline-flex;
    align-items: center;
    font-size: 1.7rem;
    margin: 0rem 0.5rem 0rem 0.5rem !important;
  }
  
  .side-menu a small {
    font-size: 0.95rem;
    /* Sidebar font size */
    font-weight: normal;
    margin: 0rem 1rem 0rem 1rem !important;
    font-family: 'Open Sans', sans-serif;
  }
  
  #menu-toggle:checked~.sidebar {
    width: 60px;
  }
  
  #menu-toggle:checked~.sidebar .side-header span {
    display: none;
  }
  
  #menu-toggle:checked~.main-content {
    margin-left: 60px;
    width: calc(100% - 60px);
  }
  
  #menu-toggle:checked~.main-content header {
    left: 60px;
  }
  
  #menu-toggle:checked~.sidebar .profile,
  #menu-toggle:checked~.sidebar .side-menu a small {
    display: none;
  }
  
  #menu-toggle:checked~.sidebar .side-menu a {
    font-size: 1.3rem;
    padding: 0.7rem 0rem 0.7rem 0rem;
    /* control menu height here */
    text-align: center;
    /* control toggle menu icons align here center, left or right */
  }
  
  #menu-toggle:checked~.sidebar .side-menu a span {
    font-size: 1.3rem;
  }
  
  .main-content {
    margin-left: 165px;
    width: calc(100% - 165px);
    transition: margin-left 300ms;
  }
  
  header {
    position: fixed;
    right: 0;
    top: 0;
    left: 165px;
    z-index: 100;
    height: 60px;
    box-shadow: 0px 5px 5px -5px rgb(0 0 0 /10%);
    background-color: #2471a3;
    transition: left 300ms;
  }
  
  .header-content,
  .header-menu {
    display: flex;
    align-items: center;
  }
  
  .header-content {
    justify-content: space-between;
    padding: 1rem 1rem;
    color: #fff!important;
  }
  
  .header-content label:first-child span {
    font-size: 1.3rem;
  }
  
  .header-content label {
    cursor: pointer;
  }
  
  .header-menu {
    justify-content: flex-end;
    padding-top: .5rem;
  }
  
  .page-content {
    height: 100vh;
    padding: 1.3rem 1rem;
    background: #f1f4f9;
  }
  
  @media (min-width: 320px) and (max-width: 480px) {
    .sidebar {
      left: -165px;
      z-index: 90;
    }
    header {
      left: 0;
      width: 100%;
    }
    .main-content {
      margin-left: 0;
      width: 100%;
    }
    #menu-toggle:checked~.sidebar {
      left: 0;
    }
    #menu-toggle:checked~.sidebar {
      width: 165px;
    }
    #menu-toggle:checked~.sidebar .side-header span {
      display: inline-block;
    }
    #menu-toggle:checked~.sidebar .profile,
    #menu-toggle:checked~.sidebar .side-menu a small {
      display: block;
    }
    #menu-toggle:checked~.sidebar .side-menu a span {
      font-size: 1.7rem;
    }
    #menu-toggle:checked~.main-content header {
      left: 0px;
    }
  }
</style>


<body>
  <input type="checkbox" id="menu-toggle">
  <div class="sidebar">
    <div class="side-header">
      <h3>L<span>ogo</span></h3>
    </div>

    <div class="side-content">
      <p></p>
      <div class="side-menu">
        <ul>
          <li>
            <a href="" class="active">
              <span class="las la-home"><small>Dashboard</small></span>
            </a>
          </li>
          <li>
            <a href="">
              <span class="las la-user-alt"><small>Profile</small></span>
            </a>
          </li>
          <li>
            <a href="">
              <span class="las la-envelope"><small>Mailbox</small></span>
            </a>
          </li>
          <li>
            <a href="">
              <span class="las la-clipboard-list"><small>Projects</small></span>
            </a>
          </li>
          <li>
            <a href="">
              <span class="las la-shopping-cart"><small>Orders</small></span>
            </a>
          </li>
          <li>
            <a href="">
              <span class="las la-tasks"><small>Tasks</small></span>
            </a>
          </li>
        </ul>
      </div>
    </div>
  </div>

  <div class="main-content">

    <header>
      <div class="header-content">
        <label for="menu-toggle">
                    <span class="las la-bars"></span>
                </label>
      </div>
    </header>


    <main>

      <div class="page-header">
        <h1>Dashboard</h1>
        <small>Home / Dashboard</small>
      </div>

      <div class="page-content">

        Page content goes here...

      </div>

    </main>

  </div>
</body>

To see changes go to Mobile view or Resize browser, then open Menu and click outside, it is not closing.

Please help me do this.

May be i need to add JavaScript code

I have tried to resolve this but failed, i wish someone may help.


Solution

  • Well well. They made a hacky trick, making the menu button be a label for a checkbox. The checkbox rules if it's :checked govern the style of the side menu.

    Now all it takes is to detect if a click was inside the .page-content and if so, uncheck the menu button checkbox. It worked when on the correct screen width (mobile).

    However, on other display width, the :checked state behaves the opposite of the desired effect. That's why I check first the window.innerWidth.

    document.addEventListener('mousedown', function(event) {
      var elem = event.target;
      var closest = elem.closest(".page-content");
    
      if (window.innerWidth <= 480) {
        if (closest) {
          // hide menu
          document.getElementById("menu-toggle").checked = false
        }
      }
    })
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
      <title>Admin Dashboard | Keyframe Effects</title>
      <link rel="stylesheet" href="style.css">
      <link rel="stylesheet" href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css">
    </head>
    Style section
    
    <style>
      @import url('https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@300;400;500;600&display=swap');
       :root {
        --main-color: #34425A;
        --color-dark: #34425A;
        --text-grey: #B0B0B0;
      }
      
      * {
        margin: 0;
        padding: 0;
        text-decoration: none;
        list-style-type: none;
        box-sizing: border-box;
        font-family: 'Merriweather', sans-serif;
      }
      
      #menu-toggle {
        display: none;
      }
      
      .sidebar {
        position: fixed;
        height: 100%;
        width: 165px;
        left: 0;
        bottom: 0;
        top: 0;
        z-index: 100;
        background-color: #d6eaf8;
        transition: left 300ms;
      }
      
      .side-menu ul li:hover {
        background-color: #1b4f72;
      }
      
      .side-menu a {
        color: #555;
        font-size: 1rem;
      }
      
      .side-menu a:hover {
        color: #fff;
        /* Change menu hover text color here */
      }
      
      .side-header {
        background-color: #2471a3;
        height: 60px;
        display: flex;
        justify-content: center;
        align-items: center;
      }
      
      .side-header h3,
      side-head span {
        color: #fff;
        font-weight: 400;
      }
      
      .side-content {
        padding: 2rem 0rem;
        height: calc(100vh - 60px);
        overflow: auto;
      }
      /* width */
      
      .side-content::-webkit-scrollbar {
        width: 5px;
      }
      /* Track */
      
      .side-content::-webkit-scrollbar-track {
        box-shadow: inset 0 0 5px grey;
        border-radius: 10px;
      }
      /* Handle */
      
      .side-content::-webkit-scrollbar-thumb {
        background: #b0b0b0;
        border-radius: 10px;
      }
      /* Handle on hover */
      
      .side-content::-webkit-scrollbar-thumb:hover {
        background: #b30000;
      }
      
      .sidebar {
        /*overflow-y: auto;*/
      }
      
      .side-menu ul {
        text-align: center;
      }
      
      .side-menu a {
        display: block;
        padding: 1rem 0rem;
        text-align: left;
      }
      
      .side-menu a.active {
        background: #1b4f72;
        border-bottom: solid 1px #d6eaf8;
      }
      
      .side-menu a.active span,
      .side-menu a.active small {
        color: #fff;
      }
      
      .side-menu a span {
        min-height: 15px;
        display: inline-flex;
        align-items: center;
        font-size: 1.7rem;
        margin: 0rem 0.5rem 0rem 0.5rem !important;
      }
      
      .side-menu a small {
        font-size: 0.95rem;
        /* Sidebar font size */
        font-weight: normal;
        margin: 0rem 1rem 0rem 1rem !important;
        font-family: 'Open Sans', sans-serif;
      }
      
      #menu-toggle:checked~.sidebar {
        width: 60px;
      }
      
      #menu-toggle:checked~.sidebar .side-header span {
        display: none;
      }
      
      #menu-toggle:checked~.main-content {
        margin-left: 60px;
        width: calc(100% - 60px);
      }
      
      #menu-toggle:checked~.main-content header {
        left: 60px;
      }
      
      #menu-toggle:checked~.sidebar .profile,
      #menu-toggle:checked~.sidebar .side-menu a small {
        display: none;
      }
      
      #menu-toggle:checked~.sidebar .side-menu a {
        font-size: 1.3rem;
        padding: 0.7rem 0rem 0.7rem 0rem;
        /* control menu height here */
        text-align: center;
        /* control toggle menu icons align here center, left or right */
      }
      
      #menu-toggle:checked~.sidebar .side-menu a span {
        font-size: 1.3rem;
      }
      
      .main-content {
        margin-left: 165px;
        width: calc(100% - 165px);
        transition: margin-left 300ms;
      }
      
      header {
        position: fixed;
        right: 0;
        top: 0;
        left: 165px;
        z-index: 100;
        height: 60px;
        box-shadow: 0px 5px 5px -5px rgb(0 0 0 /10%);
        background-color: #2471a3;
        transition: left 300ms;
      }
      
      .header-content,
      .header-menu {
        display: flex;
        align-items: center;
      }
      
      .header-content {
        justify-content: space-between;
        padding: 1rem 1rem;
        color: #fff!important;
      }
      
      .header-content label:first-child span {
        font-size: 1.3rem;
      }
      
      .header-content label {
        cursor: pointer;
      }
      
      .header-menu {
        justify-content: flex-end;
        padding-top: .5rem;
      }
      
      .page-content {
        height: 100vh;
        padding: 1.3rem 1rem;
        background: #f1f4f9;
      }
      
      @media (min-width: 320px) and (max-width: 480px) {
        .sidebar {
          left: -165px;
          z-index: 90;
        }
        header {
          left: 0;
          width: 100%;
        }
        .main-content {
          margin-left: 0;
          width: 100%;
        }
        #menu-toggle:checked~.sidebar {
          left: 0;
        }
        #menu-toggle:checked~.sidebar {
          width: 165px;
        }
        #menu-toggle:checked~.sidebar .side-header span {
          display: inline-block;
        }
        #menu-toggle:checked~.sidebar .profile,
        #menu-toggle:checked~.sidebar .side-menu a small {
          display: block;
        }
        #menu-toggle:checked~.sidebar .side-menu a span {
          font-size: 1.7rem;
        }
        #menu-toggle:checked~.main-content header {
          left: 0px;
        }
      }
    </style>
    
    
    <body>
      <input type="checkbox" id="menu-toggle">
      <div class="sidebar">
        <div class="side-header">
          <h3>L<span>ogo</span></h3>
        </div>
    
        <div class="side-content">
          <p></p>
          <div class="side-menu">
            <ul>
              <li>
                <a href="" class="active">
                  <span class="las la-home"><small>Dashboard</small></span>
                </a>
              </li>
              <li>
                <a href="">
                  <span class="las la-user-alt"><small>Profile</small></span>
                </a>
              </li>
              <li>
                <a href="">
                  <span class="las la-envelope"><small>Mailbox</small></span>
                </a>
              </li>
              <li>
                <a href="">
                  <span class="las la-clipboard-list"><small>Projects</small></span>
                </a>
              </li>
              <li>
                <a href="">
                  <span class="las la-shopping-cart"><small>Orders</small></span>
                </a>
              </li>
              <li>
                <a href="">
                  <span class="las la-tasks"><small>Tasks</small></span>
                </a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    
      <div class="main-content">
    
        <header>
          <div class="header-content">
            <label for="menu-toggle">
                        <span class="las la-bars"></span>
                    </label>
          </div>
        </header>
    
    
        <main>
    
          <div class="page-header">
            <h1>Dashboard</h1>
            <small>Home / Dashboard</small>
          </div>
    
          <div class="page-content">
    
            Page content goes here...
    
          </div>
    
        </main>
    
      </div>
    </body>