Search code examples
javascripthtmlcssnavbarnav

Displaying whole page nav shade


I'm designing a navigation shade for a personal project that'll look the same on all devices vs the hamburger solely on mobile. At the moment I'm using and × for the navigation but would like to eventually animate these and the shade opening but I need it to be functional first.

My issue at the moment though is allowing the navigation shade to display on top of the site and be closed using the ×. An issue with a lot of mobile sites is that you can't tap elsewhere below the drop-down menu and this alleviates the user issue of trying to close it a different way.

Here's the code I'm using;

.site-header {
	height: 80px;
	background-color: #FFFFFF;
	display: inline-flex;
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 1;
	box-shadow: 0px 0.5px 10px #000000;
}

.site-header-fill {
	height: 80px;
}

.site-logo-container {
	height: 60px;
	margin-left: 20px;
	margin-right: auto;
	margin-top: 10px;
	margin-bottom: 10px;
	display: block;
	float: left;
}

.site-logo {
	height: 60px;
	width: auto;
	float: left;
}

.site-nav-action-container {
	height: 50px;
	width: 50px;
	max-width: 50px;
	margin-left: 10px;
	margin-right: 10px;
	margin-top: 15px;
	margin-bottom: 15px;
	display: block;
	float: right;
	text-align: right;
}

.site-nav {
	height: 100%;
	left: 0px;
	position: fixed;
	top: 0px;
	width: 100%;
	background: #3399ff;
	z-index: 2;
}

.site-nav-content {
	width: 20%;
	position: absolute;
	left: 50%;
	top: 50%;
	-webkit-transform: translate(-50%, -50%);
	transform: translate(-50%, -50%);
}

@media only screen and (max-width: 500px) {
	.site-nav-content {
		width: auto;
		position: absolute;
		left: 50%;
		top: 50%;
		-webkit-transform: translate(-50%, -50%);
		transform: translate(-50%, -50%);
	}
}

.site-nav-pages {
	text-align: center;
}
<div class="site-header ">
   <div class="site-logo-container">
      <img class="site-logo" src="https://via.placeholder.com/1000x300" alt="Logo">
   </div>
   <div class="site-nav-action-container">
      <button class="nav" onclick="location.href='/'">
         <p class="site-log-in-text w700">☰</p>
      </button>
   </div>
</div>
<div class="site-nav">
   <div class="site-nav-action-container">
      <button class="nav" onclick="location.href='/'">
         <p class="site-log-in-text w700">X</p>
      </button>
   </div>
   <div class="site-nav-content">
      <div class="site-nav-pages">
         <p>Page 1</p>
         <p>Page 2</p>
         <p>Page 3</p>
         <p>Page 4</p>
         <p>Page 5</p>
      </div>
   </div>
</div>

The problem you'll see when you run it is that the navigation shade is always present. I'm not sure which approach to take for showing it/having it hidden initially.

Ideally pressing the should open it and the × close it. It's fine for it to display over the top of the page content because it'll always fill the whole screen. I'm just not sure which approach to take.

Any help would be appreciated. Thanks in advance.


Solution

  • Use your <button class="nav"> elements to switch between states. A state can be defined in CSS, like how does it look by default and how does it look when activated. In your case you'll want to change the state of the <div class="site-nav"> element to hide by default, and show when clicking the button.

    Remove the onclick attributes on the buttons as you don't want to navigate. Instead select them in JavaScript and listen for the click. Give them both the same event handler function that will toggle a class on the site-nav element.

    In your CSS add opacity: 0 and visibility: hidden to the .site-nav styles. This will make the element transparent and hide it completely. These properties also allow you to use a transition from visible to invisible and vice versa.

    const navButtons = document.querySelectorAll('button.nav');
    const siteNav = document.querySelector('.site-nav');
    
    function onClick(event) {
      siteNav.classList.toggle('active');
    }
    
    navButtons.forEach(button => button.addEventListener('click', onClick));
    .site-header {
    	height: 80px;
    	background-color: #FFFFFF;
    	display: inline-flex;
    	position: fixed;
    	top: 0;
    	left: 0;
    	right: 0;
    	z-index: 1;
    	box-shadow: 0px 0.5px 10px #000000;
    }
    
    .site-header-fill {
    	height: 80px;
    }
    
    .site-logo-container {
    	height: 60px;
    	margin-left: 20px;
    	margin-right: auto;
    	margin-top: 10px;
    	margin-bottom: 10px;
    	display: block;
    	float: left;
    }
    
    .site-logo {
    	height: 60px;
    	width: auto;
    	float: left;
    }
    
    .site-nav-action-container {
    	height: 50px;
    	width: 50px;
    	max-width: 50px;
    	margin-left: 10px;
    	margin-right: 10px;
    	margin-top: 15px;
    	margin-bottom: 15px;
    	display: block;
    	float: right;
    	text-align: right;
    }
    
    .site-nav {
    	height: 100%;
    	left: 0px;
    	position: fixed;
    	top: 0px;
    	width: 100%;
    	background: #3399ff;
    	z-index: 2;
      opacity: 0;
      visibility: 0;
      transition: opacity 150ms ease-in-out, visibility 150ms ease-in-out;
    }
    
    .site-nav.active {
      opacity: 1;
      visibility: visible;
    }
    
    .site-nav-content {
    	width: 20%;
    	position: absolute;
    	left: 50%;
    	top: 50%;
    	-webkit-transform: translate(-50%, -50%);
    	transform: translate(-50%, -50%);
    }
    
    @media only screen and (max-width: 500px) {
    	.site-nav-content {
    		width: auto;
    		position: absolute;
    		left: 50%;
    		top: 50%;
    		-webkit-transform: translate(-50%, -50%);
    		transform: translate(-50%, -50%);
    	}
    }
    
    .site-nav-pages {
    	text-align: center;
    }
    <div class="site-header ">
       <div class="site-logo-container">
          <img class="site-logo" src="https://via.placeholder.com/1000x300" alt="Logo">
       </div>
       <div class="site-nav-action-container">
          <button class="nav">
             <p class="site-log-in-text w700">☰</p>
          </button>
       </div>
    </div>
    <div class="site-nav">
       <div class="site-nav-action-container">
          <button class="nav">
             <p class="site-log-in-text w700">X</p>
          </button>
       </div>
       <div class="site-nav-content">
          <div class="site-nav-pages">
             <p>Page 1</p>
             <p>Page 2</p>
             <p>Page 3</p>
             <p>Page 4</p>
             <p>Page 5</p>
          </div>
       </div>
    </div>