Second level of sidebar - javascript

I want to create a sidebar with a submenu that extends to the right instead of down. A rough picture below:
I'm fairly new with flexbox and that is all I could come up with:
HTML:
<div class="d-flex align-items-stretch">
<nav class="side-navigation">
<ul class="sidebar-nav d-flex flex-column">
<li class="sidebar-nav-expand d-flex toggle">
<a class="nav-link sidebar-nav-expand-toggle py-3" href="#">
<span class="icon icon-ic_compute"></span>
<span class="nav-item-text">Menu1</span>
<span class="float-right"><i class="fas fa-mortar-pestle"></i></span>
</a>
<div class="sidebar-nav-expand-items">
<ul class="sidebar-nav">
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url1">
<span class="nav-item-text">Menu1 subitem1</span>
</a>
</li>
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url2">
<span class="nav-item-text">Menu1 subitem2</span>
</a>
</li>
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url3">
<span class="nav-item-text">Menu1 subitem3</span>
</a>
</li>
</ul>
</div>
</li>
<li class="sidebar-nav-expand d-flex">
<a class="nav-link sidebar-nav-expand-toggle py-3" href="#">
<span class="icon icon-ic_management"></span>
<span class="nav-item-text">Menu2</span>
<span class="float-right"><i class="fas fa-mortar-pestle"></i></span>
</a>
<div class="sidebar-nav-expand-items">
<ul class="sidebar-nav">
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url21">
<span class="nav-item-text">Menu2 subitem1</span>
</a>
</li>
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url22">
<span class="nav-item-text">Menu2 subitem2</span>
</a>
</li>
<li class="sidebar-nav-item py-3">
<a class="nav-link py-1" href="#some-url23">
<span class="nav-item-text">Menu2 subitem3</span>
</a>
</li>
</ul>
</div>
</li>
<li class="sidebar-nav-expand">
<a class="nav-link py-3" href="#some-url">
<span class="icon icon-ic_administration"></span>
<span class="nav-item-text">Direct link</span>
<span class="float-right"><i class="fas fa-mortar-pestle"></i></span>
</a>
</li>
</ul>
</nav>
<div class="main">
Content
</div>
</div>
SCSS:
$white: #fff;
$whitesmoke: #ECEFF1;
$aliceblue: #f1f6ff;
$light-gray: #D6DADC;
$blue: #2971FB;
$light-blue: #BFD5FE;
$black: #263238;
$light-black: #364046;
$orange: #FF8F00;
.side-navigation {
max-width: 540px;
transition: all 0.3s;
}
.sidebar-nav {
display: flex;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
padding-left: 0;
margin-bottom: 0;
list-style: none;
.nav-link {
display: block;
padding: .75rem 1rem;
color: $white;
text-decoration: none;
background: 0 0;
&:hover {
color: $orange;
}
}
.sidebar-nav-item {
width: 100%;
}
.sidebar-nav-expand {
width: 100%;
background-color: $black;
&.toggle {
.sidebar-nav-expand-toggle {
color: $orange;
}
.sidebar-nav-expand-items {
margin-left: 0;
}
}
.sidebar-nav-expand-toggle {
width: 270px;
z-index: 2;
}
.sidebar-nav-expand-items {
width: 270px;
height: 100%;
background-color: $light-gray;
transition: margin-left .25s ease-in-out;
margin-left: -270px;
color: $black;
.nav-link {
color: $black;
&:hover {
color: $orange;
}
&:not(.active) {
margin-left: 8px;
}
&.active {
border-left: solid 8px $orange;
}
}
}
}
}
.main {
width: 100%;
min-height: 100vh;
padding-left: 10px;
}
JS:
$('.sidebar-nav-expand-toggle').on('click', function() {
let self = $(this);
self.parent('.sidebar-nav-expand').toggleClass('toggle');
$('.main').toggleClass('toggle');
});
https://jsfiddle.net/cj4375er/
As you can see the child is not properly hidden under the parent and submenus are stacked, if a menu is opened I want all other menus to close. Also, there is too much space between menu items.
I would just need some points in the right direction. If there is an example of a similar case I would be happy.

I see that you tried to cover the submenu bar using z-index: 2 at that sidebar-nav-expand-toggle. However, your items are not properly hidden because your sidebar-nav-expand-toggle has no background (i.e. it's transparent). The background is actually from sidebar-nav-expand (#263238) that bleeds through the sidebar-nav-expand-toggle because sidebar-nav-expand-toggle is transparent. Therefore, the solution is to instruct the sidebar-nav-expand-toggle to inherit the same background as its parent, resulting in this code below:
.sidebar-nav-expand-toggle {
width: 270px;
z-index: 2;
background: inherit;
}
Your menus are stacked because you did not handle the closing of the other submenus that may be open (you merely toggled the one that is clicked, but you didn't close the ones that may be open that are not clicked). A simple addition to your JS code fixes this:
$('.sidebar-nav-expand-toggle').on('click', function() {
let self = $(this);
let toggled = self.parent('.sidebar-nav-expand').hasClass('toggle')
hideAllSubmenu()
if (toggled)
self.parent('.sidebar-nav-expand').removeClass('toggle')
else
self.parent('.sidebar-nav-expand').addClass('toggle')
$('.main').toggleClass('toggle');
});
function hideAllSubmenu() {
let submenus = $('.sidebar-nav-expand-toggle')
submenus.parent('.sidebar-nav-expand').removeClass('toggle')
}
There is too much space between menu items. My suggestion would be to make a flexbox that has only the three menu items with padding. And then, for each of those menus (can be a or div), create a div inside it that has position: absolute based on those menus. You can then slide it out when clicked by using transform: translate. That way, the height is not dependent on a wrapping container's height.
Also, I see that you are using SCSS. I really suggest reading about BEM selectors here to better utilize SCSS to create a more easily readable code.
EDIT:
I've added a little working example of what I meant by using position: absolute and still being able to push the main content to the right when the submenu expands. Take a look below (please adjust this minimal working example to what you need):
function resetSubmenuStyles() {
let submenus = document.querySelectorAll('.submenu div')
for (let submenu of submenus) {
submenu.style.width = ''
submenu.style.visibility = ''
}
}
document.querySelector('#menuOne').addEventListener('click', e => {
let submenu = document.querySelector('.submenu')
let submenuOne = document.querySelector('#submenuOne')
let submenuStyle = window.getComputedStyle(submenuOne)
let submenuWidth = parseInt(submenuStyle.getPropertyValue('width')) - parseInt(submenuStyle.getPropertyValue('padding-left')) - parseInt(submenuStyle.getPropertyValue('padding-right'))
resetSubmenuStyles()
if (submenuWidth == 0) {
submenu.style.width = '20%'
submenuOne.style.width = '100%'
submenuOne.style.visibility = 'visible'
}
else {
submenu.style.width = ''
submenuOne.style.width = ''
submenuOne.style.visibility = ''
}
})
document.querySelector('#menuTwo').addEventListener('click', e => {
let submenu = document.querySelector('.submenu')
let submenuTwo = document.querySelector('#submenuTwo')
let submenuStyle = window.getComputedStyle(submenuTwo)
let submenuWidth = parseInt(submenuStyle.getPropertyValue('width')) - parseInt(submenuStyle.getPropertyValue('padding-left')) - parseInt(submenuStyle.getPropertyValue('padding-right'))
resetSubmenuStyles()
if (submenuWidth == 0) {
submenu.style.width = '20%'
submenuTwo.style.width = '100%'
submenuTwo.style.visibility = 'visible'
}
else {
submenu.style.width = ''
submenuTwo.style.width = ''
submenuTwo.style.visibility = ''
}
})
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: Helvetica, sans-serif;
}
html, body {
width: 100vw;
height: 100%;
}
body {
display: flex;
}
.menu {
width: 20%;
height: 100%;
background: #000;
color: #FFF;
}
.menu h1 {
padding: 20px;
cursor: pointer;
}
.submenu {
position: relative;
width: 0%;
height: 100%;
background: #333;
color: #FFF;
}
.submenu div {
visibility: hidden;
position: absolute;
width: 0;
top: 0;
left: 0;
padding: 20px;
}
<div class = "menu">
<h1 id = "menuOne">Test</h1>
<h1 id = "menuTwo">Test</h1>
</div>
<div class = "submenu">
<div id = "submenuOne">
Submenu Test One
</div>
<div id = "submenuTwo">
Submenu Test Two
</div>
</div>
<div id = "main">Some Content</div>

Related

Event Listener Only Adds Class For A Second - I Want It Permanent

Working on a side nav that appears when I click on the burger menu. I am relatively new to this. I'm using event listeners to add and remove a class. But what's happening is the click is registered, the transition starts and then is cut off and doesn't continue, it goes back to original state.
const menuBtn = document.querySelector(".burgerMenu");
const sMenu = document.querySelector("#sideMenu");
const bI1 = document.querySelector(".burgerIcon1");
const bI2 = document.querySelector(".burgerIcon2");
const bI3 = document.querySelector(".burgerIcon3");
menuBtn.addEventListener('click', () => {
if (!sMenu.classList.contains('menuAway')) {
sMenu.classList.add('menuAway');
} else {
sMenu.classList.remove('menuAway');
}
if (!bI1.classList.contains('oneOnClick')) {
bI1.classList.add('oneOnClick');
} else {
bI1.classList.remove('oneOnClick');
}
if (!bI2.classList.contains('twoOnClick')) {
bI2.classList.add('twoOnClick');
} else {
bI2.classList.remove('twoOnClick');
}
if (!bI3.classList.contains('threeOnClick')) {
bI3.classList.add('threeOnClick');
} else {
bI3.classList.remove('threeOnClick');
}
})
.menu {
background: var(--gradient);
height: 100vh;
width: 38%;
position: fixed;
right: 0;
top: 0;
z-index: 3;
display: flex;
align-items: center;
padding-left: 5%;
opacity: 0.92;
transition: 0.3s;
}
.menuAway {
right: -75vw;
}
.menu li {
font-size: 1.8rem;
text-transform: uppercase;
font-weight: 500;
line-height: 4rem;
}
.menu li:hover {
text-decoration: underline;
}
.burgerMenu {
z-index: 4;
}
.burgerIcon {
width: 35px;
height: 3px;
margin: 5px auto;
background-color: #282828;
border-radius: 10px;
transition: 0.3s;
}
.oneOnClick {
transform: translate(0px, 8px) rotate(45deg);
}
.twoOnClick {
width: 0px;
}
.threeOnClick {
transform: translate(0px, -8px) rotate(-45deg);
}
<div class="navParent">
<div class="navBar">
<a href="index.html">
<img src="Assets/logo.svg" alt="Inform Logo" class="smallLogo">
</a>
<a href="" class="burgerMenu">
<div class="burgerIcon burgerIcon1"></div>
<div class="burgerIcon burgerIcon2"></div>
<div class="burgerIcon burgerIcon3"></div>
</a>
</div>
<section class="menu menuAway" id="sideMenu">
<ul>
<a href="about.html">
<li>About Us</li>
</a>
<a href="projects.html">
<li>Projects</li>
</a>
<a href="articles.html">
<li>Articles</li>
</a>
<a href="contact.html">
<li>Contact Us</li>
</a>
</ul>
</section>
</div>
This happens because of the <a href=""> so when you click the link you actually navigate, causing the page to reload. I suggest replacing the link with a button, or for a quick fix, do <a href="javascript:void(0)">
Also, you can make your code a lot easier to read by using classList.toggle instead of the if/else blocks
https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle
E.g. replace
if (!sMenu.classList.contains('menuAway')) {
sMenu.classList.add('menuAway');
} else {
sMenu.classList.remove('menuAway');
}
With
sMenu.classList.toggle('menuAway')

How to add mutually exclusivity on toggling dropdown menu

I have a menu with dropdown submenus. I'm trying to close an item when clicking on another, so that I don't have multiple items open at the same time. In a previous question: How to Apply .nextElementSibling to the next item of a dropdown menu a user suggested that I take a look at the function called mutually exclusivity. How can I add it to my menu?
var dropdownBtn = document.querySelectorAll('.menu-btn');
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
menuContent.classList.toggle("show");
}));
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container > .item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
Store previously clicked menu in a variable, and clear it's class if another menu was clicked
var dropdownBtn = document.querySelectorAll('.menu-btn'),
lastOpened = null;
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
menuContent.classList.toggle("show");
if (lastOpened && lastOpened !== menuContent)
lastOpened.classList.remove("show");
lastOpened = menuContent;
}));
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container > .item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
You could add a function that closes all menu's except the one you pass into it:
var dropdownBtn = document.querySelectorAll('.menu-btn');
dropdownBtn.forEach(btn => btn.addEventListener('click', function() {
var menuContent = this.nextElementSibling;
closeMenusExcept(menuContent);
menuContent.classList.toggle("show");
}));
function closeMenusExcept(menuContent) {
dropdownBtn.forEach((element) => {
if (menuContent !== element.nextElementSibling) {
element.nextElementSibling.classList.remove("show");
}
})
}
.menu-btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.menu-btn:hover {
background: #000;
color: #fff;
}
.drop_container {
display: none;
background-color: #017575;
transition: 0.3s;
opacity: 0;
}
.drop_container.show {
display: contents;
visibility: visible;
opacity: 1;
}
.drop_container>.item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown-menu">
<div class="menu-btn">One</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="menu-btn">Two</div>
<div class="drop_container">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>
Note
I changed the class names so they easier to type and read.
We'll use the programming paradigm call event delegation.
Bind event to an ancestor tag (a tag that holds all of the tags you want to control)
Figure I
const menu = document.querySelector(".dropdown");
menu.addEventListener('click', //...
Next, design an event handler that only reacts when the right tags are clicked
Figure II
//...
function(event) {
// This is the tag the user clicked
const clicked = event.target;
// Find .show
const current = document.querySelector('.show');
// See if the clicked tag has .show class
let state = clicked.matches('.show');
// Only react if the clicked tag has .btn class
if (clicked.matches('.btn')) {//...
Note: The .show class is now assigned to the .btn. See Figure IV
Figure III
//...
// if there already is a .show
if (current) {
// remove .show
current.classList.remove('show');
}
// if the clicked tag did not have .show previously...
if (!state) {
// ...add .show to it
clicked.classList.add("show");
}
}
});
In CSS this ruleset uses the adjacent sibling combinator which is equivalent to .nextElementSibling
Figure IV
/* .btn.show + .list <=that's the next sibling */
.show+.list {
display: block;
}
Removed visibility and opacity since original state is display:none which is a switch that inhibits any sort of transition (also removed). The display: content was changed to display: block. display: content doesn't have any standard behavior, when applied, the .items were black and white, but once replaced their original green returned. As a general rule dealing with CSS is if you don't see it being used in the examples, don't use it because there's probably a good reason why it isn't being used.
With this setup you never have to worry about how many button/items you have as long as it is inside the ancestor tag. Also, if you add any button/items dynamically, they do not need to be bound to the event. All you'll ever need is one event listener for each event you want to listen for.
const menu = document.querySelector(".dropdown");
const btns = document.querySelectorAll('.btn');
menu.addEventListener('click', function(event) {
const clicked = event.target;
const current = document.querySelector('.show');
let state = clicked.matches('.show');
if (clicked.matches('.btn')) {
if (current) {
current.classList.remove('show');
}
if (!state) {
clicked.classList.add("show");
}
}
});
.btn {
background: #e0e0e0;
padding: 10px;
margin: 5px 0px 0px 0px;
}
.btn:hover {
background: #000;
color: #fff;
}
.list {
display: none;
background-color: #017575;
}
.show+.list {
display: block;
}
.list>.item {
display: flex;
flex-direction: column;
margin-left: 10px;
padding: 10px 0px 0px 0px;
}
<div class="dropdown">
<div class="btn">One</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="btn">Two</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
<div class="btn">Three</div>
<div class="list">
<a class="item" href="#">Contact Us</a>
<a class="item" href="#">Visit Us</a>
</div>
</div>

Navbar not changing background colour when scrolling

Tried a few different JavaScript options and I am hoping it is something really simple that I am missing.
Several attempts and Google searches as to how exactly I do this seems to lead me on a road to nowhere for every different solution so far.
Any suggestions as to how to fix this would be apppreciated.
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
document.getElementsByClassName(".navbar").style.backgroundColor = "transparent";
} else {
document.getElementsByClassName(".navbar").style.backgroundColor = "black";
}
}
ul {
padding: 0;
margin: 0;
}
ul li {
list-style-type: none;
}
.hero-img {
filter: brightness(30%);
background-size: cover;
}
.hero-image-overlay {
width: 50%;
margin: 0 auto;
padding: 1rem 0;
}
.navbar {
padding: 0;
background-color: transparent;
position: fixed;
top: 0;
width: 100%;
}
.navbar ul {
display: flex;
position: relative;
}
.navbar ul li {
padding: .5rem 0;
color: white;
padding: 1rem;
width: 100%;
}
ul a {
display: inline-block;
}
.nav-img {
width: 175px;
}
.header-li:hover,
.header-li:focus {
color: orangered;
transition: all .3s;
}
.header-li {
display: none;
}
.news-posts {
max-width: 1250px;
columns: 500px 2;
margin: 0 auto;
}
<html>
<body>
<!-- start of Header area -->
<header>
<div class="hero-image">
<img class="hero-img" src="img/lower-height-team-photo.jpg" alt="team-photo">
</div>
<nav class="navbar">
<ul class="header-ul">
<a href="#">
<li class="img-li"><img src="img/imageedit_3_3953793469.png" alt="" class="nav-img"></li>
</a>
<a href="#">
<li class="header-li">About Us</li>
</a>
<a href="#">
<li class="header-li">Team</li>
</a>
<a href="#">
<li class="header-li">Fixtures/Results</li>
</a>
<a href="#">
<li class="header-li">News</li>
</a>
<a href="#">
<li class="header-li">Contact</li>
</a>
</ul>
<i class="fa fa-bars fa-2x"></i></>
</nav>
</header>
</body>
</html>
Many thanks to any solutions you can offer.
Firstly, remove . sign when getting element by class name, it should be
document.getElementsByClassName("navbar")
and not
document.getElementsByClassName(".navbar")
Also, take a note that getElementsByClassName returns an array so, in order to set a background color to work, it should be something like this:
document.getElementsByClassName(".navbar")[0].style.backgroundColor = "black";
This is complete javascript code
function scrollFunction() {
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
document.getElementsByClassName("navbar")[0].style.backgroundColor = "transparent";
} else {
document.getElementsByClassName("navbar")[0].style.backgroundColor = "black";
}
}
// Do not forget to call the function
scrollFunction();
Also remove display: none in header-li class

How to close hamburger nav on click of the <a> tags?

As the title states, I am wanting my hamburger navbar to close when I click on the tags I have tried many ways for the last couple hours but am unable to solve my problem?
I Have tried setting the hide() property with jquery but no luck think it may be because i am pretty new to JS and am just wanting to get my website finished.
const menuBtn = document.querySelector(".menu-btn");
const mobileContent = document.querySelector(".mobile-content");
const mobileItem = document.querySelector(".mobile-item");
const mobileItems = document.querySelectorAll(".mobile-items");
// Set Initial State Of Menu
let showMenu = false;
menuBtn.addEventListener("click", toggleMenu);
function toggleMenu() {
if (!showMenu) {
menuBtn.classList.add("close");
mobileContent.classList.add("show");
mobileItem.classList.add("show");
mobileItems.forEach(item => item.classList.add("show"));
// Set Menu State
showMenu = true;
} else {
menuBtn.classList.remove("close");
mobileContent.classList.remove("show");
mobileItem.classList.remove("show");
mobileItems.forEach(item => item.classList.remove("show"));
// Set Menu State
showMenu = false;
}
}
.mobile-nav {
display: block;
position: fixed;
width: 100%;
top: 0;
z-index: 3;
}
.mobile-nav .menu-btn {
position: absolute;
z-index: 3;
right: 20px;
top: 20px;
cursor: pointer;
}
.mobile-nav .menu-btn .btn-line {
width: 28px;
height: 3px;
margin: 0 0 5px 0;
background: #333;
}
.mobile-content {
position: fixed;
top: 0;
width: 100%;
opacity: 0.9;
visibility: hidden;
}
.mobile-content.show {
visibility: visible;
}
.mobile-content .mobile-item {
display: flex;
flex-flow: column;
align-items: center;
justify-content: center;
float: right;
width: 100%;
height: 100vh;
overflow: hidden;
margin: 0;
padding: 0;
background: blue;
list-style: none;
transform: translate3d(0, -100%, 0);
}
.mobile-content .mobile-link {
display: inline-block;
position: relative;
font-size: 2rem;
padding: 1rem 0;
font-weight: bold;
color: #333;
text-decoration: none;
}
<!-- Mobile Nav -->
<div class="mobile-nav">
<div class="menu-btn">
<div class="btn-line"></div>
<div class="btn-line"></div>
<div class="btn-line"></div>
</div>
<h2>MATTY</h2>
<nav class="mobile-content">
<ul class="mobile-item">
<li class="mobile-items">
<a href="#about-me" class="mobile-link">
ABOUT
</a>
</li>
<li class="mobile-items">
<a href="#the-portfolio" class="mobile-link">
PORTFOLIO
</a>
</li>
<li class="mobile-items">
<a href="#" class="mobile-link">
BLOG
</a>
</li>
<li class="mobile-items">
<a href="#contact-me" class="mobile-link">
CONTACT
</a>
</li>
</ul>
</nav>
</div>
I had to remove some of your CSS as it was not working in the snippet.
Recommend you use element.classList.toggle() as below.
Note how much simpler the code becomes.
EDIT: Clicking any a tag will now close menu
document.addEventListener("click", (e) => {
if(e.target.matches('.menu-btn')
|| e.target.matches('.btn-line')
|| e.target.matches('a')) {
toggleMenu();
}
});
function toggleMenu() {
document.querySelector('.mobile-content').classList.toggle('hide');
}
.btn-line {
display: block;
width: 50px;
margin: 5px;
border: 2px solid black;
}
.mobile-nav {
display: block;
width: 100%;
z-index: 3;
}
.mobile-content {
position: fixed;
width: 100%;
opacity: 0.9;
}
.hide {
display: none;
}
<!-- Mobile Nav -->
<div class="mobile-nav">
<div class="menu-btn">
<span class="btn-line"></span>
<span class="btn-line"></span>
<span class="btn-line"></span>
</div>
<a href="#home">
<h2>MATTY</h2>
</a>
<nav class="mobile-content hide">
<ul class="mobile-item">
<li class="mobile-items">
<a href="#about-me" class="mobile-link">
ABOUT
</a>
</li>
<li class="mobile-items">
<a href="#the-portfolio" class="mobile-link">
PORTFOLIO
</a>
</li>
<li class="mobile-items">
<a href="#" class="mobile-link">
BLOG
</a>
</li>
<li class="mobile-items">
<a href="#contact-me" class="mobile-link">
CONTACT
</a>
</li>
</ul>
</nav>
</div>
#MPB A good way to dabble into some simple JQuery language is a way to fix your problem. A quick and easy way to make a good Hamburger Navigation menue is with the toggleClass(); function in JQuery. Just make a #keyframes-animation within an un-set class and toggleClass(); will switch between the two seamlessly. I do this all the time, comment if you'd like me to forward the code to you for you to use.

JS dropdown menu being hidden? or not working?

After thoroughly trying to fix this issue - I need a little help.
I am trying to make a website that has a navbar (made with bootstrap) for websites and I am making a small drop-down menu for smaller screens (I haven't added this functionality yet, I just want it to work first). I haven't styled it much yet either.
The problem is that I know my button and code is working (because I have a codepen showing that it works), but in my website, I cannot see the drop-down menu. Not sure if it is hidden or what but I just can't figure this out.
Here is the HTML (because I have to put something...):
<div class = "dropdown">
<button onclick = "menuBtn ()" class = "dropBtn">Menu</button>
<div id = "dropCollapse" class = "dropdownContent">
<a class = "contentLinks" href = "#about">About</a>
<a class = "contentLinks" href = "#team">Team</a>
<a class = "contentLinks" href = "#photos">Photos</a>
<a class = "contentLinks" href = "#shirts">T-Shirts</a>
<a class = "contentLinks" href = "#contact">Contact</a>
</div>
</div>
I have played around with z-index (in a number of places but if you have a suggestion, feel free to make it and I will try it). I have taken the menu out of the navbar (thinking it had something to do with that). But mostly I am just confused - nothing else really answered my question about this menu issue. I feel like there is something small that I am overlooking and I just can't figure it out.
Here is a fiddle showing the basic outline of my website with the menu not working: https://jsfiddle.net/nekochan/eh69segg/1/
A few things I noticed:
you were using jQuery but did not define jQuery to load. If you do an "inspect element" you'll see that $ is not defined
also you had a few missing divs, and an anchor wasn't closed
I'd recommend just using purely jQuery if you're going to go that approach - it's a very simple example. Here is your updated fiddle - notice the toggle animates nicely :)
https://jsfiddle.net/qdL9mch2/1/
/* global $ */
$(document).ready(function() {
//makes the masethead fit the whole screen
$("#masthead").css("min-height", $(window).height());
//mobile menu button collapse
$(".dropBtn").on("click", function(){
$("#dropCollapse").toggle("show");
});
// Close the dropdown menu if the user clicks outside of it
//update to jquery
window.onclick = function(event) {
if (!event.target.matches('.dropBtn')) {
var dropdowns = document.getElementsByClassName("dropdownContent");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
};
});
there are multiple errors there in your HTML for example <a class="navBrand" href="#masthead"> is not closing and your menuBtn is not being called, I would recommend you to use jquery completely if you have it included inside your project see here your code working
//mobile menu button collapse
function menuBtn() {
document.getElementById("dropCollapse").classList.toggle("show");
}
/* global $ */
$(document).ready(function() {
$("#my-button").click(function() {
document.getElementById("dropCollapse").classList.toggle("show");
})
//makes the masethead fit the whole screen
$("#masthead").css("min-height", $(window).height());
// Close the dropdown menu if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches('.dropBtn')) {
var dropdowns = document.getElementsByClassName("dropdownContent");
for (var i = 0; i < dropdowns.length; i++) {
var openDropdown = dropdowns[i];
if (openDropdown.classList.contains('show')) {
openDropdown.classList.remove('show');
}
}
}
};
});
.main {
font-family: 'Roboto', sans-serif;
width: 100%;
margin: 0px;
padding: 0px;
overflow-x: hidden;
overflow-y: hidden;
}
.body {
position: relative;
}
#navBar {
margin-bottom: 0;
background-color: black;
font-family: 'Permanent Marker', cursive;
}
.brandImage {
height: 60px;
width: auto;
}
#navHeader {}
#navItem {}
#navLink {
text-decoration: none;
}
.dropBtn {
background-color: #4caf50;
color: white;
padding: 16px;
font-size: 16px;
border: none;
cursor: pointer;
}
.dropBtn:hover,
.dropBtn:focus {
background-color: #3e8e41;
}
.dropdown {
position: relative;
display: inline-block;
}
.dropdownContent {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 9999;
}
.contentLinks {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.contentLinks:hover {
background-color: #f1f1f1;
}
.show {
display: block;
}
#media (max-width: 960px) {
#large-menu {
display: none;
}
.brandImage {
float: left;
}
}
#masthead {
background-color: #65737e;
background-image: url(https://static.pexels.com/photos/285286/pexels-photo-285286.jpeg);
width: 100%;
height: auto;
background-size: cover;
background-position: bottom center;
display: flex;
align-items: center;
min-height: 100%;
min-height: 100vh;
}
.headerText {
font-size: 90px;
font-family: 'Permanent Marker', cursive;
color: #fff;
}
.headerTagline {
font-size: 60px;
font-family: 'Permanent Marker', cursive;
color: #fff;
}
.anchor {
display: block;
height: 50px;
margin-top: -50px;
visibility: hidden;
}
.sectionHeader {
font-family: 'Permanent Marker', cursive;
padding: 20px 20px 20px 20px;
}
.sectionText {
padding: 20px 20px 20px 20px;
}
#aboutBox {
background-color: #c0c5ce;
padding: 20px 0 20px;
}
#teamBox {
background-color: #a7adba;
padding: 20px 0 20px;
}
#workBox {
background-color: #65737e;
padding: 20px 0 20px;
}
#shirtBox {
background-color: #4f5b66;
padding: 20px 0 20px;
}
#socialBox {
background-color: #343d46;
padding: 20px 0 20px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">
<nav class="navbar navbar-inverse navbar-fixed-top" id="navBar">
<div class="container-fluid">
<div class="navHeader navbar-left">
<a class="navBrand" href="#masthead"></a>
<ul class="nav navbar-nav navbar-right" id="large-menu">
<li class="navItem">
<a class="navLink" href="#about">About</a>
</li>
<li class="navItem">
<a class="navLink" href="#team">Team</a>
</li>
<li class="navItem">
<a class="navLink" href="#photos">Photos</a>
</li>
<li class="navItem">
<a class="navItem" href="#shirts">T-Shirts</a>
</li>
<li class="navItem">
<a class="navLink" href="#contact">Contact</a>
</li>
</ul>
</div>
<div class="dropdown">
<button class="dropBtn" id="my-button">Menu</button>
<div id="dropCollapse" class="dropdownContent">
<a class="contentLinks" href="#about">About</a>
<a class="contentLinks" href="#team">Team</a>
<a class="contentLinks" href="#photos">Photos</a>
<a class="contentLinks" href="#shirts">T-Shirts</a>
<a class="contentLinks" href="#contact">Contact</a>
</div>
</div>
</nav>
<div class="container text-center" id="masthead">
<div class="col-sm-12">
<h1 class="headerText"></h1>
<p class="headerTagline"></p>
</div>
</div>
<span class="anchor" id="about"></span>
<div class="container-fluid" id="aboutBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">About Us</h2>
<p class="sectionText">We're all about that chedda</p>
</div>
</div>
</div>
<span class="anchor" id="team"></span>
<div class="container-fluid" id="teamBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Meet the team</h2>
<p class="sectionText">pictures of team go here</p>
</div>
</div>
</div>
<span class="anchor" id="photos"></span>
<div class="container-fluid" id="workBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Our Work</h2>
<p class="sectionText">pictures go here</p>
</div>
</div>
</div>
<span class="anchor" id="shirts"></span>
<div class="container-fluid" id="shirtBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">T-shirts Preview</h2>
<p class="sectionText">pictures of tshirts go here</p>
</div>
</div>
</div>
<span class="anchor" id="contact"></span>
<div class="container-fluid" id="socialBox">
<div class="row">
<div class="col-sm-12">
<h2 class="sectionHeader">Contact Us</h2>
<p class="sectionText">links to social media and contact us form</p>
</div>
</div>
</div>

Categories