The corresponding dropdown element should display below it
BONUS: Clicking anywhere on the page besides the 3 menu items
hide any visible menu item
Look into the matches() function
Hamburger icon / nav elements:
When user clicks hamburger icon, side menu should be displayed
When user clicks “close” button in side menu, it should be hidden again
You should only be adding JS here!
My HTML and CSS are identical in the starter & solution code
HTML
<ul class="nav">
<li id="menu-1-button">Why Slack?</li>
<li id="menu-2-button">Solutions</li>
<li id="menu-3-button">Resources</li>
<li>Pricing</li>
</ul>
</section>
<div class="nav-right">
<p class="workspaces">Your Workspaces</p>
<div class="hamburger-menu" id="menu-trigger">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2522641/hamburger.svg" alt="Hamburger icon">
</div>
</div>
</header>
<!--Main content-->
<section class="placeholder"></section>
<!--Side menu-->
<aside class="side-menu-position side-menu-design" id="side-menu">
<header class="side-menu-header">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2522641/slack.svg" alt="Slack logo">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/2522641/x.svg" alt="Close this menu" id="menu-close">
</header>
<ul class="side-menu-content">
<li>Why Slack?</li>
<li>Pricing</li>
<li>About Us</li>
<li class="side-menu-workspace">Your Workspaces</li>
<li class="side-menu-download">Download Slack</li>
</ul>
</aside>
<!--Dropdown Menus, notice how they are asides listed just inside the body - no deeper -->
<aside class="dropdown-menu" id="menu-1">
<h2 class="menu-header">About the Product</h2>
<ul class="menu-item-list">
<li><a href="#">How it works</a></li>
<li><a href="#">Security</a></li>
<li><a href="#">Customers</a></li>
<li><a href="#">Enterprise</a></li>
</ul>
</aside>
<aside class="dropdown-menu" id="menu-2">
<h2 class="menu-header">Slack for Every Team</h2>
<ul class="menu-item-list">
<li><a href="#">Engineering</a></li>
<li><a href="#">IT</a></li>
<li><a href="#">Customer Support</a></li>
<li><a href="#">Project Management</a></li>
<li><a href="#">Sales</a></li>
<li><a href="#">Marketing</a></li>
<li><a href="#">Human Resources</a></li>
</ul>
</aside>
<aside class="dropdown-menu" id="menu-3">
<h2 class="menu-header">Go Further With Slack</h2>
<ul class="menu-item-list">
<li><a href="#">Download</a></li>
<li><a href="#">Blog</a></li>
<li><a href="#">Help Center</a></li>
<li><a href="#">e-Books</a></li>
<li><a href="#">Reports</a></li>
<li><a href="#">API</a></li>
</ul>
</aside>
CSS
body {
font-family: 'Lato', sans-serif;
color: #454545;
}
.placeholder {
background: lightslategray;
height: 100vh;
}
.global-header {
background-color: white;
display: flex;
flex-direction: row;
justify-content: space-between;
height: 40px;
padding: 15px 25px;
width: calc(100% - 50px);
}
/* NAV */
.nav-left {
align-items: center;
display: flex;
}
.logo {
display: flex;
align-items: center;
}
.logo svg {
width: 150px;
}
.nav {
display: none;
flex-direction: row;
align-items: center;
margin: 0;
padding-left: 0;
}
@media (min-width: 1085px) {
.nav {
display: flex;
}
}
ul {
list-style: none;
}
.nav li {
font-size: 14px;
margin: 0 20px;
cursor: pointer;
}
.nav-right {
align-items: center;
display: flex;
justify-content: flex-end;
margin-right: 45px;
}
/* DROPDOWN MENU */
.dropdown-menu {
background-color: white;
box-shadow: 0 0 2rem rgba(0,0,0,.1);
/* `display: none` hides the element when the page loads - how could we change this when our JS event takes place? */
display: none;
padding: 15px;
position: absolute; /* pops element up in the dom */
top: 60px;
width: 250px;
z-index: 10;
}
/* element has this class and ID */
.dropdown-menu#menu-1 {
left: 190px;
}
.dropdown-menu#menu-2 {
left: 290px;
min-width: 400px;
}
.dropdown-menu#menu-3 {
left: 390px;
min-width: 400px;
}
.menu-header {
font-size: 12px;
margin: 0;
padding: 0 10px 8px 10px;
text-transform: uppercase;
}
.menu-item-list {
margin: 0;
padding-left: 0;
}
/* https://developer.mozilla.org/en-US/docs/Web/CSS/columns
Guide to Responsive-Friendly CSS Columns
*/
#menu-2 .menu-item-list,
#menu-3 .menu-item-list {
column-count: 2;
column-gap: 20px;
}
.menu-item-list li a,
.menu-item-list li a:visited,
.menu-item-list li a:focus {
color: #454545;
display: block;
padding: 10px;
text-decoration: none;
}
.menu-item-list li a:hover {
background-color: rgb(242,242,242);
color: #1264a3;
}
/* Fade-in header */
#fade-in-header {
display: none;
position: fixed;
top: 0;
}
#top-nav {
position: fixed;
}
.show {
display: block;
}
/* SIDE MENU */
.workspaces {
background-color: #611f69;
border-radius: 10px;
color: white;
cursor: pointer;
display: none;
padding: 8px 16px;
transition: all 420ms ease-in-out;
}
/* Notice you can do a hover state on an element, not just <a> links */
.workspaces:hover {
background-color: #4a154b
}
@media (min-width: 1085px) {
.workspaces {
/* Hidden below 1085px - see above rule */
display: block;
}
}
.hamburger-menu {
display: block; /* display:none starts to show up with responsive */
cursor: pointer;
}
@media (min-width: 1085px) {
.hamburger-menu {
display: none;
}
}
/* OFF CANVAS MENU
* Slack has an image with a translucent bg which combines bg color and image together
* position: fixed with 0,0,0,0 positions streches across the viewport
* z-index: 2 keeps it on top of the rest of the page
* I'm breaking the side-menu parent into two styles, one position and on design, so you can see how this looks better
* You don't have to do it this way at all...but it helps to see the separation of concerns here
*/
.side-menu-position {
padding-top: 25px;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
}
.side-menu-design {
background-color: #611f69;
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/2522641/sidebar-background.png');
background-size: 1300px 700px;
background-repeat: repeat;
cursor: pointer;
opacity: 0;
transform: translateX(100%);
transition: 0.4s ease-in-out;
}
/* on top we need spacing from the border, so we have to use padding */
/* but we also want that bottom margin to bleed to the edge, so no margins here */
.side-menu-header {
border-bottom: 1px solid rgba(255,255,255,.1); /* based on slack look, very faint */
display: flex;
justify-content: space-between;
padding: 0 25px 25px 25px;
}
/* Main content is pretty easy for layouts, pattern you'll see in web dev */
/* The more text an element has, the easier it is to layout - BAM wisdom bomb! */
.side-menu-content {
color: #fff;
font-size: 24px; /* could use ems here too */
margin: 25px;
padding-left: 0;
}
.side-menu-content li {
list-style: none;
margin-bottom: 25px;
}
.side-menu-workspace {
margin-bottom: 8px;
text-align: center;
}
.side-menu-download {
background-color: #fff;
color: #611f69;
padding: 15px 0;
text-align: center;
width: 100%;
}
/* Sticks the nav to the top of the page */
#top-nav {
position: fixed;
}
/* Animation classes */
.show-menu {
opacity: 1;
transform: translateX(0%);
}
JavaScript
const menu1Button = document.getElementById('menu-1-button');
const menu2Button = document.getElementById('menu-2-button');
const menu3Button = document.getElementById('menu-3-button');
// We'll also assign all 3 of our menu dropdown elements to variables
const menu1Dropdown = document.getElementById('menu-1');
const menu2Dropdown = document.getElementById('menu-2');
const menu3Dropdown = document.getElementById('menu-3');
// Note that we are never reassigning the value of any of these variables - which is why we're using the `const` keyword instead of the `let` keyword
// Okay. Let's talk through what functionality we want for one button. Let's start with the first menu element - "Why Slack?" - we've stored that as `menu1Button` variable above.
// So we'll have something like:
// menu1Button.addEventListener("someevent", someFunction);
// What’s the event? It’s when the user clicks that element. What event is that in JS? It’s the “click” event – https://developer.mozilla.org/en-US/docs/Web/API/Element/click_event
// So now we have:
// menu1Button.addEventListener("click", someFunction);
// Now we need the function to run! Let's not name it `someFunction` - we'll name it after the functionality we want it to execute! We want it to display the first dropdown menu element - so how about `displayMenuOne`?
// So now we have:
// menu1Button.addEventListener("mouseover", displayMenuOne);
// Now we just need our `displayMenuOne` function!
// It should *display* the element with ID "menu-1" - stored as `menu1Dropdown` variable above.
// How can we edit that element to display it? We *could* use the "style" property (remember when we did `document.body.style.backgroundColor` in the color switcher activity in Lesson 10?).
// However, it's easier to use CSS classes - and we have this `.show` rule in our CSS... so let's just add the "show" class to the "menu1Dropdown" element
// function displayMenuOne() {
// menu1Dropdown.classList.add("show");
// }
// Last piece: what if one of the other dropdowns is being displayed? Remember - we don't always want to rely on the initial state of our page. The initial state is that none of the dropdowns are displayed, but what if I've clicked on `menu1Button` when the second menu is already visible?
// Let's make sure to remove the `show` class on our other 2 dropdown elements, whether or not that class is present on the element.
// So we end up with:
menu1Button.addEventListener("click", displayMenuOne);
function displayMenuOne() {
menu1Dropdown.classList.add("show");
menu2Dropdown.classList.remove("show");
menu3Dropdown.classList.remove("show");
}
// Let's repeat this for our other 2 menu button elements.
menu2Button.addEventListener("click", displayMenuTwo);
menu3Button.addEventListener("click", displayMenuThree);
function displayMenuTwo() {
// show menu 2
menu2Dropdown.classList.add("show");
// hide menus 2 and 3 if they are open
menu1Dropdown.classList.remove("show");
menu3Dropdown.classList.remove("show");
}
function displayMenuThree() {
// show menu 3
menu3Dropdown.classList.add("show");
// hide menus 1 and 2 if they are open
menu1Dropdown.classList.remove("show");
menu2Dropdown.classList.remove("show");
}
// SIDE MENU
// There's a menu icon present at or below a viewport width of 1085px.
// It has the ID of `menu-trigger`.
// Let's assign it to a variable.
const menuDisplayButton = document.getElementById('menu-trigger');
// What event are we listening for on that element?
// A click!
menuDisplayButton.addEventListener("click", displaySideMenu);
// When the side menu is visible, it has a close button with ID `menu-close`.
// Let's add a click listener for that element that will hide the side menu.
const menuCloseButton = document.getElementById("menu-close");
console.log(menuCloseButton);
menuCloseButton.addEventListener("click", hideSideMenu);
// Now we just need these 2 functions - `displaySideMenu` and `hideSideMenu`
// The class that displays our side menu element is `show-menu`
// so `displaySideMenu` will add that class to the side menu element
// and `hideSideMenu` will remove that class
const sideMenu = document.getElementById('side-menu');
function displaySideMenu() {
sideMenu.classList.add("show-menu");
}
function hideSideMenu() {
sideMenu.classList.remove("show-menu");
}
The corresponding dropdown element should display below it
BONUS: Clicking anywhere on the page besides the 3 menu items
hide any visible menu item
Look into the matches() function
Hamburger icon / nav elements:
When user clicks hamburger icon, side menu should be displayed
When user clicks “close” button in side menu, it should be hidden again
You should only be adding JS here!
My HTML and CSS are identical in the starter & solution code
Please focus on the bonus part