0

const mobileNav = document.querySelector(".mobile-nav-div");
const mobileNavItems = document.querySelectorAll(".mobile-nav-div > ul > li");
const mobileNavButton = document.querySelector('.nav-dropdown-icon');




function mobileNavInteract() {
  if (mobileNav.style.display === "") {
    mobileNav.className = 'mobile-nav-div';
    mobileNav.style.display = "block";

  } else if (mobileNav.style.display === 'block') {
    mobileNav.className = "reverse";
    mobileNav.style.display = "";
  }
}

mobileNavButton.addEventListener('click', mobileNavInteract)
  @font-face {
  src: url(fonts/RobotoSlab-Regular.ttf);
  font-family: roboto;
}

body,
html {
  font-family: arial;
  margin: auto;
}

.nav-wrapper-second {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  background-color: rgb(85, 85, 85);
  padding: 5px 250px;
}

.links {
  margin-right: 70px;
  width: 500px;
}

.mobile-nav-div {
  display: none;
}

.nav-dropdown-icon {
  padding-left: 20px;
  height: 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.nav-dropdown-icon>div {
  width: 30px;
  height: 2px;
  background-color: white;
}


/*MEDIA QUERIES*/

@media (max-width: 815px) {
  .mobile-nav-div {
    background-color: grey;
    width: 100%;
    animation-name: slide;
    animation-duration: 0.3s;
  }
  .mobile-nav {
    padding-left: 15px;
    margin: 0;
    display: flex;
    flex-direction: column;
    list-style: none;
    height: 300px;
    width: 100%;
    align-items: flex-start;
    justify-content: space-between;
  }
  .mobile-nav>li {
    height: 16%;
    width: 100%;
    border-bottom: 1px solid rgb(207, 207, 207);
  }
  .mobile-nav>li>a {
    text-decoration: none;
    color: white;
    display: flex;
    align-items: center;
    margin-top: auto;
    width: 100%;
    height: 100%;
  }
  .mobile-nav>li>a:hover::after {
    position: absolute;
    margin-top: 48px;
    content: '';
    height: 2px;
    left: 0;
    background: rgb(0, 0, 0);
    animation-name: test;
    animation-duration: 1s;
    animation-fill-mode: forwards;
  }
  @keyframes test {
    from {
      width: 0px;
    }
    to {
      width: 100%;
    }
  }
  .reverse {
    /* a class to be added for the close animation*/
    display: flex;
    background-color: grey;
    width: 100%;
    animation-name: reverse-slide !important;
    animation-duration: 0.5s;
    animation-fill-mode: forwards;
  }
  @keyframes slide {
    from {
      height: 0px;
    }
    to {
      height: 300px
    }
  }
  @keyframes reverse-slide {
    from {
      height: 300px;
    }
    to {
      height: 0px
    }
  }
  @media (max-width: 768px) {}
  @media (max-width: 400px) {}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="app.js" defer></script>
  <link rel="stylesheet" href="icons/icomoon/style.css">
  <link rel="stylesheet" href="style.css">

</head>

<body>
  <section class="nav-wrapper">

    <div class="nav-wrapper-second">
      <div class="links">

        <div class='nav-dropdown-icon'>
          <div></div>
          <div></div>
          <div></div>
        </div>

      </div>
      <div class="search-div">
        <input type="text" placeholder="Search">
      </div>
    </div>

    <div class="mobile-nav-div">
      <ul class="mobile-nav">
        <li><a href="">Home</a></li>
        <li><a href="">About</a></li>
        <li><a href="">Courses</a></li>
        <li><a href="">Staff</a></li>
        <li><a href="">Blog</a></li>
        <li><a href="">Contact</a></li>
      </ul>
    </div>
  </section>
  <div>
    Lorem ipsum, dolor sit amet consectetur adipisicing elit. Similique, consectetur!
  </div>
</body>

</html>

I am trying to make a dropdown menu for the mobile size of my site. I'm using a bit of CSS animations. The parent div containing all of the elements is set to display:none by default, until you open it using the menu button, where it becomes set to display:block. an animation plays in order to cause it to slide down while opening.

There is also an animation that causes the div to slide back up when you close it using the same menu button. Problem is that the border-bottom property and the ::after pseudo selectors of the links (a tag) contained within the parent div still show (all other elements hide though) after closing (hiding) the parent div.

I can use visibility:hidden to hide it, but God forbid I ignore this issue like it never existed. I don't intend to continue unless I discover that this issue is unsolvable. This is the order of the elements in descending order from highest parent to child ( div > ul > li > a ).

I'm using vanilla JS, no frameworks.

Here is the link to the fiddle if you don't want to use the one above: https://jsfiddle.net/unyohg42/27/ It's just the code for the mobile navigation. I tried to remove as much bloat as possible.

halfer
  • 19,824
  • 17
  • 99
  • 186
Qsand
  • 11
  • 3
  • 3
    Please put your runnable example **here, on-site** using Stack Snippets (the `[<>]` toolbar button); [here's how to do one](https://meta.stackoverflow.com/questions/358992/), not just linked. Three reasons: People shouldn't have to go off-site to help you; some sites are blocked for some users; and links rot, making the question and its answers useless to people in the future. Even without making it runnable, we obviously need the HTML, not just the CSS. But there's no reason not to make it runnable here. – T.J. Crowder Nov 06 '20 at 11:09

2 Answers2

0

Your logic for making a mobile menu is not the best. Please do some research. There are tons of examples with pure javascript on the web.

Anyway, to solve your specific problem. just add overflow:hidden to your .reverse element.

const mobileNav = document.querySelector(".mobile-nav-div");
const mobileNavItems = document.querySelectorAll(".mobile-nav-div > ul > li");
const mobileNavButton = document.querySelector('.nav-dropdown-icon');




function mobileNavInteract() {
    if (mobileNav.style.display === "") {
        mobileNav.className = 'mobile-nav-div';
        mobileNav.style.display = "block";
        
        
        // for(i=0; i<mobileNavItems.length;i++) {
        //     mobileNavItems[i].style.borderBottom = '1px solid rgb(207, 207, 207)';
        // }

        
        
    }

    else if (mobileNav.style.display === 'block') {
        mobileNav.className = "reverse";
         // mobileNav.style.display = ""; -> NOT NEEDED

        // for(i=0; i<mobileNavItems.length;i++) {
        //     mobileNavItems[i].style.border = 'none';
        // }

        
    }
}

mobileNavButton.addEventListener('click', mobileNavInteract)
@font-face {
  src: url(fonts/RobotoSlab-Regular.ttf);
  font-family: roboto;
}

body,
html {
  font-family: arial;
  margin: auto;
}

.nav-wrapper-second {
  display: flex;
  width: 100%;
  align-items: center;
  justify-content: space-between;
  background-color: rgb(85, 85, 85);
  padding: 5px 250px;
}

.links {
  margin-right: 70px;
  width: 500px;
}


.mobile-nav-div {
  display: none;
}

.nav-dropdown-icon {
  padding-left: 20px;
  height: 20px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.nav-dropdown-icon>div {
  width: 30px;
  height: 2px;
  background-color: white;
}



/*MEDIA QUERIES*/


@media (max-width: 815px) {

  .mobile-nav-div {
    background-color: grey;
    width: 100%;
    animation-name: slide;
    animation-duration: 0.3s;
  }

  .mobile-nav {
    padding-left: 15px;
    margin: 0;
    display: flex;
    flex-direction: column;
    list-style: none;
    height: 300px;
    width: 100%;
    align-items: flex-start;
    justify-content: space-between;
  }

  .mobile-nav>li {
    height: 16%;
    width: 100%;
    border-bottom: 1px solid rgb(207, 207, 207);
  }

  .mobile-nav>li>a {
    text-decoration: none;
    color: white;
    display: flex;
    align-items: center;
    margin-top: auto;
    width: 100%;
    height: 100%;
  }

  .mobile-nav>li>a:hover::after {
    position: absolute;
    margin-top: 48px;
    content: '';
    height: 2px;
    left: 0;
    background: rgb(0, 0, 0);
    animation-name: test;
    animation-duration: 1s;
    animation-fill-mode: forwards;
  }

  @keyframes test {
    from {
      width: 0px;
    }

    to {
      width: 100%;
    }
  }

  .reverse {
    /* a class to be added for the close animation*/
    display: flex;
    overflow:hidden;
    background-color: grey;
    width: 100%;
    animation-name: reverse-slide !important;
    animation-duration: 0.5s;
    animation-fill-mode: forwards;
  }

  @keyframes slide {
    from {
      height: 0px;
    }

    to {
      height: 300px
    }
  }

  @keyframes reverse-slide {
    from {
      height: 300px;
    }

    to {
      height: 0px
    }
  }




  @media (max-width: 768px) {}

  @media (max-width: 400px) {}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="app.js" defer></script>
    <link rel="stylesheet" href="icons/icomoon/style.css">
    <link rel="stylesheet" href="style.css">
    
</head>
<body>
    <section class="nav-wrapper">
        
        <div class="nav-wrapper-second">
            <div class="links">
               
                <div class = 'nav-dropdown-icon'>
                    <div></div>
                    <div></div>
                    <div></div>
                </div>
                
            </div>
            <div class="search-div">
                <input type="text" placeholder ="Search">
            </div>
        </div>

        <div class = "mobile-nav-div">
            <ul class="mobile-nav">
                <li><a href="">Home</a></li>
                <li><a href="">About</a></li>
                <li><a href="">Courses</a></li>
                <li><a href="">Staff</a></li>
                <li><a href="">Blog</a></li>
                <li><a href="">Contact</a></li>
            </ul>
        </div>
    </section>
    <div>
        Lorem 
        ipsum, dolor
         sit amet consectetur
          adipisicing elit. Similique,
         consectetur!
    </div>
</body>
</html>

Further info

mobileNav.style.display = "" doesn't give it display:none . It just resets the display property to the default one or the one specified in your CSS. What does style.display = '' actually do? . So you are not hiding the menu. You are just giving it a different classname (' reverse ') which has an animation attached to it. That makes the menu have height:0 . But without overflow:hidden , the items inside the menu are still shown. Not only the borders, but also the texts. ( they are white and you cannot see them but they are there )

Mihai T
  • 17,254
  • 2
  • 23
  • 32
  • I don't know if i'm replying you Mihai (not exactly familiar with the stack overflow environment)...i know there are a lot of tools available for animations, but this is my first shot learning animation. I know my code isn't very good, but i'm trying to learn. Thanks alot. your answer worked for me! – Qsand Nov 06 '20 at 11:25
  • why doesn't the display hide everything though if i may ask? – Qsand Nov 06 '20 at 11:29
  • @Qsand Please see my edit where i explained what's happening. Also don't forget to rate my answer as accepted ( green tick ). Thank you ! :D – Mihai T Nov 06 '20 at 11:40
  • Noted. So, how then do I set the display to none? Because style.display = "none" doesn't seem to work. (I'm still learning css here, so I still have some more to learn). – Qsand Nov 06 '20 at 12:24
0

instead of setting style to nothing,

 mobileNav.style.display = "";

set it to "none" again you just have to adjust your check then too

if (mobileNav.style.display === "") {

gets to

if (mobileNav.style.display === "none") {

working fiddle https://jsfiddle.net/pg14krej/

john Smith
  • 17,409
  • 11
  • 76
  • 117
  • hi John. I tried setting it to display = "none" severally, but for some reason, the button does not open the menu when clicked. and if i try to console.log the style.display, i just get an empty space in my console. – Qsand Nov 06 '20 at 11:27
  • updated my answer with a fiddle, `.style` referrs to the inline style attribute, therefore you have to add style="display:none;" to the html instead of css – john Smith Nov 06 '20 at 12:00