2

I want to make the hamburger menu close when I either click on a link(which all lead to a location on the same page), or click somewhere away from the menu. Currently, I have to click the link, and then close the menu manually by hitting the hamburger button again.

When it comes to javascript, I am pretty newbish. This is basically the one thing left to get my portfolio running.

function myFunction() {
  let x = document.getElementById("myNav");
  if (x.className === "nav") {
    x.className += " open";
  } else {
    x.className = "nav";
  }
}
body {
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
}

#topper {
  display: grid;
  grid-template-rows: auto auto auto auto;
  grid-template-areas: "header" "navigation";
}

.nav {
  font-family: 'Markazi Text', sans;
  padding-top: 10px;
  position: fixed;
  width: 100%;
  display: grid;
  text-align: center;
  grid-template-columns: 15% auto 0 0 0 0 0;
  grid-template-areas: "ham . navPhotos navVideos navGraphic navWeb navAbout";
}

.nav.open {
  height: 100%;
  background-color: white;
  align-content: start;
  grid-template-columns: 15% 70% 15%;
  grid-template-areas: "ham navPhotos ." ". navPhotos ." ". navVideos ." ". navGraphic ." ". navWeb ." ". navAbout .";
}

#ham {
  grid-area: ham;
}

#navPhotos {
  grid-area: navPhotos;
}

#navVideos {
  grid-area: navVideos;
}

#navGraphic {
  grid-area: navGraphic;
}

#navWeb {
  grid-area: navWeb;
}

#navAbout {
  grid-area: navAbout;
}

@media only screen and (min-width: 601px) {
  #topper {
    width: 100%;
    background-color: white;
    display: grid;
    grid-template-rows: auto auto auto auto;
    grid-template-areas: "header" "navigation";
  }
  .indexgallery {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  #ham {
    display: none;
  }
  .nav {
    padding-top: 0;
    position: static;
    width: 600px;
    margin: 0 auto;
    background-color: white;
    display: grid;
    grid-template-columns: auto auto auto auto auto;
    grid-template-areas: "navPhotos navVideos navGraphic navWeb navAbout";
  }
  .nav.open {
    padding-top: 0;
    position: static;
    width: 600px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: auto auto auto auto auto;
    grid-template-areas: "navPhotos navVideos navGraphic navWeb navAbout";
  }
  #myNav {
    grid-area: navigation;
  }
}

.empty {
  height: 100px;
  color: rgba(0, 0, 0, 0);
}
<div class="nav" id="myNav">
  <div id="ham"><a href="javascript:void(0);" onclick="myFunction()">&#9776;</a></div>
  <div id="navPhotos"><a href="#photo">Photography</a></div>
  <div id="navVideos"><a href="#video">Videography</a></div>
  <div id="navGraphic"><a href="#dig">Graphic</a></div>
  <div id="navWeb"><a href="#web">Web Design</a></div>
  <div id="navAbout"><a href="#abt">About</a></div>
</div>
showdev
  • 28,454
  • 37
  • 55
  • 73
Richard B
  • 21
  • 3

2 Answers2

1

Here's one method.

The toggle function accepts two parameters: the element to toggle and the state that's desired. If the state is true AND the nav is closed, the nav will open. If the state is false OR the nav is open, the nav will close.

I bound an event listener to the document that closes the nav. I also prevented a click on the humburger from bubbling up to the document with stopPropagation(). That way, clicking the hamburger won't also fire the click on the document.

var nav = document.getElementById("myNav");
var ham = document.getElementById("ham");

function toggleNav(x, t) {
  if (t && x.className === "nav") {
    x.className += " open";
  } else {
    x.className = "nav";
  }
}

ham.addEventListener('click', function(e) {
  e.preventDefault();
  e.stopPropagation();
  toggleNav(nav, true);
});

document.addEventListener('click', function(e) {
  toggleNav(nav, false);
});
body {
  margin: 0;
  font-family: Arial, Helvetica, sans-serif;
}

#topper {
  display: grid;
  grid-template-rows: auto auto auto auto;
  grid-template-areas: "header" "navigation";
}

.nav {
  font-family: 'Markazi Text', sans;
  padding-top: 10px;
  position: fixed;
  width: 100%;
  display: grid;
  text-align: center;
  grid-template-columns: 15% auto 0 0 0 0 0;
  grid-template-areas: "ham . navPhotos navVideos navGraphic navWeb navAbout";
}

.nav.open {
  height: 100%;
  background-color: white;
  align-content: start;
  grid-template-columns: 15% 70% 15%;
  grid-template-areas: "ham navPhotos ." ". navPhotos ." ". navVideos ." ". navGraphic ." ". navWeb ." ". navAbout .";
}

#ham {
  grid-area: ham;
}

#navPhotos {
  grid-area: navPhotos;
}

#navVideos {
  grid-area: navVideos;
}

#navGraphic {
  grid-area: navGraphic;
}

#navWeb {
  grid-area: navWeb;
}

#navAbout {
  grid-area: navAbout;
}

@media only screen and (min-width: 601px) {
  #topper {
    width: 100%;
    background-color: white;
    display: grid;
    grid-template-rows: auto auto auto auto;
    grid-template-areas: "header" "navigation";
  }
  .indexgallery {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
  #ham {
    display: none;
  }
  .nav {
    padding-top: 0;
    position: static;
    width: 600px;
    margin: 0 auto;
    background-color: white;
    display: grid;
    grid-template-columns: auto auto auto auto auto;
    grid-template-areas: "navPhotos navVideos navGraphic navWeb navAbout";
  }
  .nav.open {
    padding-top: 0;
    position: static;
    width: 600px;
    margin: 0 auto;
    display: grid;
    grid-template-columns: auto auto auto auto auto;
    grid-template-areas: "navPhotos navVideos navGraphic navWeb navAbout";
  }
  #myNav {
    grid-area: navigation;
  }
}

.empty {
  height: 100px;
  color: rgba(0, 0, 0, 0);
}
<div class="nav" id="myNav">
  <div id="ham"><a href="#">&#9776;</a></div>
  <div id="navPhotos"><a href="#photo">Photography</a></div>
  <div id="navVideos"><a href="#video">Videography</a></div>
  <div id="navGraphic"><a href="#dig">Graphic</a></div>
  <div id="navWeb"><a href="#web">Web Design</a></div>
  <div id="navAbout"><a href="#abt">About</a></div>
</div>

You might also consider using classList.

showdev
  • 28,454
  • 37
  • 55
  • 73
  • showdev, that worked! I removed e.preventDefault(); from the last bit of javascript, because it kept resetting the entire page(which probably wasn't apparent, since you couldn't see my entire webpage). Works great now, thanks for the input! – Richard B Jun 06 '19 at 21:08
1

You can wrap the menu items in a wrapper like this,

  <div id='wrapper' onclick='hide()'>
    <div id="navPhotos"><a href="#photo">Photography</a></div>
    <div id="navVideos"><a href="#video">Videography</a></div>
    <div id="navGraphic"><a href="#dig">Graphic</a></div>
    <div id="navWeb"><a href="#web">Web Design</a></div>
    <div id="navAbout"><a href="#abt">About</a></div>
  </div>

then just remove the class 'open',

    function hide() {
        let x = document.getElementById("wrapper");
        if (x.className === "nav open") {
            x.className = "nav";
        }
    }
shahriar hasan
  • 113
  • 1
  • 3
  • 10