skip to Main Content

I’m trying to create a dropdown list of buttons that only show up when the mouse pointer hover on the first button that is not hidden, and the dropdown list disappear when pointer leave when it no longer hover.
The problem is that I want when the pointer leaves the initial button boundaries, the other buttons still be visible when the pointer hover over them and not disappear.

Note:
i’m still a beginner in JavaScript so please don’t judge my way of explaining the problem or my coding. I’m still learning and hopefully I will get better.

The code:

   <!DOCTYPE html>
<html >
    <head>
    <meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale= 1.0">
    </head>
    <style>
        html {
            margin: 0;
            padding: 0;
        }
        header {
            position: absolute;
            top: 0;
            left: 0;
            margin: 0;
            height: 100px;
            width: 100%;
            background-color: red;
            display: flex;
            flex-direction: row;
            justify-content: flex-start;
            align-items: center;
            
        }

        .btns-container {
            position: absolute;
            top: 20px;
            margin: 20px;
            padding: 0;
            display: flex;
            flex-direction: column;
            z-index: 1;
        }
        .btns {
            width: 100px;
            height: 30px;
            border: none;
            cursor: pointer;
            margin: 1px;
        }
        #thBtn {
            background-color: #C7C8CC;
            color: #3C3633;
        }
        #thBtn:hover {
            background-color: #3C3633;
            color: #C7C8CC;
        }
        #liBtn {
            background-color: #FFFBF5;
            color: #C3ACD0;
            display: none;
            
         }
        #liBtn:hover {
            background-color: #C3ACD0;
            color: #FFFBF5;
        }
        #liBtn:active {
            background-color: #FFFBF5;
            color: #C3ACD0;
        }
        #daBtn {
            background-color: black;
            color: white;
            display: none;

        }
        #daBtn:hover {
            background-color: white;
            color: black;
        }
        #daBtn:active {
            background-color: black;
            color: white;
        }
        #naBtn {
            background-color: #0C359E;
            color: #F6F5F5;
            display: none;

        }
        #naBtn:hover {
            background-color: #F6F5F5;
            color: #0C359E;
        }
        #naBtn:active {
            background-color: #0C359E;
            color: #F6F5F5;
        }


    </style>
    <body>
        <header>
        <div class="btns-container">
            <button id="thBtn" class="btns">Theme</button>
            <button id="liBtn" class="btns">Light</button>
            <button id="daBtn" class="btns">Dark</button>
            <button id="naBtn" class="btns">Navy</button>
        </div>
        </header>
        <main>
            <div style="background-color: aqua; width: 300px; height: 300px;"></div>
        </main>

    <script>
        const themeBtn = document.getElementById("thBtn");
        const lightBtn = document.getElementById("liBtn");
        const darkBtn = document.getElementById("daBtn");
        const navyBtn = document.getElementById("naBtn");

        themeBtn.addEventListener('pointerenter', () => {
             lightBtn.style.display = "block";
             darkBtn.style.display = "block";
             navyBtn.style.display = "block";



        });
        themeBtn.addEventListener("pointerout", () => {
            lightBtn.style.display = "none";
            darkBtn.style.display = "none";
            navyBtn.style.display = "none";

        });
    </script>
    </body>
    
</html>

I’ve tried pointerup and pointerdown and still did’t work.

2

Answers


  1. Chosen as BEST ANSWER

    UPDATE: I found a solution!

    I fixed it by wrapping the buttons inside a container and only giving the intial button the mouseover event and then inside the function I gave the container the mouseleave event so the buttons get hidden when the mouse leave the boundaries of the container, which by the way have 0 margin and padding.

    Here is the new code:

    const themeButton = document.getElementById("thBtn").addEventListener("mouseover", () => {
    
                const themeBtn = document.getElementById("thBtn");
                const lightBtn = document.getElementById("liBtn");
                const darkBtn = document.getElementById("daBtn");
                const navyBtn = document.getElementById("naBtn");
                const btnsContainer = document.getElementById("btns");
    
                 lightBtn.style.display = "block";
                 darkBtn.style.display = "block";
                 navyBtn.style.display = "block";
    
                btnsContainer.addEventListener("mouseleave", () => {
                    lightBtn.style.display = "none";
                    darkBtn.style.display = "none";
                    navyBtn.style.display = "none";
                });
             });
    

  2. It’s not the most optimal way, I’ve taken some shortcuts, but in a better context, you should make dropdown generation dynamic and manage the generation of data to be displayed in dropdowns on the JavaScript side. This will be cleaner and more maintainable.

    When you lose the focus of your first button, the element will be closed, otherwise it will always remain open as long as you are in the context of your button.

    const buttonFirstDropdown = document.querySelector(".button-first-dropdown");
    const buttonSecondDropdown = document.querySelector(".button-second-dropdown");
    
    const firstDropdown = document.querySelector('.first-dropdown');
    const secondDropdown = document.querySelector('.second-dropdown');
    
    const dropdownFirstDropdown = firstDropdown.querySelector('.dropdown-list');
    const dropdownSecondDropdown = secondDropdown.querySelector('.dropdown-list');
    
    buttonFirstDropdown.addEventListener('mouseover', (event) => {
        dropdownFirstDropdown.classList.add('active');
    })
    
    buttonSecondDropdown.addEventListener('mouseover', (event) => {
        dropdownSecondDropdown.classList.add('active');
    })
    
    document.body.addEventListener('mouseleave', () => {
        dropdownFirstDropdown.classList.remove('active');
        dropdownSecondDropdown.classList.remove('active');
    })
    body {
      font-family: sans-serif;
    }
    
    #app {
      display: flex;
      flex-direction: row wrap;
      align-items: flex-start;
    }
    
    .dropdown {
      width: 100px;
      margin: 20px;
    }
    
    .dropdown-list {
      padding: 0;
      margin: 0;
    }
    
    .dropdown-item {
      cursor: pointer;
      padding: 5px;
      border: 1px solid #ccc;
    }
    
    .first-dropdown.dropdown .dropdown-list, 
    .second-dropdown.dropdown .dropdown-list {
      height: 0;
      overflow: hidden;
    }
    
    .first-dropdown .dropdown-list.active, 
    .second-dropdown .dropdown-list.active {
      height: 100%;
      overflow: auto;
    }
    <!DOCTYPE html>
    <html>
      <head>
        <title>JavaScript Sandbox</title>
        <link rel="stylesheet" href="styles.css" />
        <meta charset="UTF-8" />
      </head>
    
      <body>
        <div id="app">
          <div class="first-dropdown dropdown">
            <button type="button" class="button-first-dropdown">Open It (1)</button>
            <div class="dropdown-list">
              <!-- You can dynamically generate your list here -->
              <div class="dropdown-item">Element 1</div>
              <div class="dropdown-item">Element 2</div>
              <div class="dropdown-item">Element 3</div>
            </div>
          </div>
    
          <div class="second-dropdown dropdown">
            <button type="button" class="button-second-dropdown">Open It (2)</button>
            <div class="dropdown-list">
              <!-- You can dynamically generate your list here -->
              <div class="dropdown-item">Element 1</div>
              <div class="dropdown-item">Element 2</div>
              <div class="dropdown-item">Element 3</div>
            </div>
          </div>
        </div>
    
        <script src="./index.js"></script>
      </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search