I have been trying to make my mobile navigation menu to toggle back when I click outside the navigation links or when I click on one of them. I have looked around and I only find jQuery example which I'm avoiding. I want to have an example with JavaScript ES6. So, how can I make it work?
Here is my code:
const navSlide = () => {
const burger = document.querySelector('.burger');
const nav = document.querySelector('.nav-links');
burger.addEventListener('click', () => {
nav.classList.toggle('nav-active');
})
}
navSlide();
html {
scroll-behavior: smooth;
}
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
font-family: Gelion;
background-color: #fa555204;
}
.nav-links li a, .logo {
text-decoration: none;
}
ul {
list-style: none;
}
.main-nav {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 18px;
height: 10%;
padding: 20px 0;
}
.nav-links {
display: flex;
}
.nav-links li {
padding: 0 15px;
}
.burger{
display: none;
}
/* Media Query - Mobile */
#media only screen and (max-width: 700px) {
body {
overflow-x: hidden;
}
/* Burger Menu */
.nav-links {
position: fixed;
right: 0;
height: 100vh;
width: 60%;
top: 0vh;
background-color: var(--secondary-color);
display: flex;
justify-content: space-evenly;
align-items: center;
flex-direction: column;
transform: translateX(100%);
transition: transform 0.5s ease-in;
z-index: 1;
}
.nav-links li a {
color: #fff;
}
.nav-active {
transform: translateX(0%);
}
.main-nav .burger {
display: block;
cursor: pointer;
font-size: 35px;
}
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet"/>
<nav class="main-nav">
<a href="#" class="logo" />Logo</a>
<ul class="nav-links">
<li>Overview</li>
<li>Contagion</li>
<li>Symptoms</li>
<li>Prevention</li>
<li>Contact</li>
</ul>
<div class="burger">
<i class="fas fa-bars"></i>
</div>
</nav>
you can use css very easy for this Using :focus Selector
checkout this link : https://www.w3schools.com/cssref/sel_focus.asp
or try this
.classname:focus{
//your code here will run while client focused in this class
}
Related
I've been trying to follow a few tutorials to turn a horizontal menubar into a drop-down hamburger menu when displayed on smaller screens, but I'm struggling to make it come together properly. I noticed a lot of tutorials seem to do away with ul/li format, which I'd like to save for semantic and accessible reasons, but this has left me struggling to get the dropdown to appear correctly on the screen.
My goal is to allow the hamburger menu to open the four menu items, centered on the screen, below the top header bar. I've managed to make the hamburger menu "work," but it's opening the items not centered and not below the top menubar. Any suggestions that don't require revamping the entire menubar code, if possible?
const menu = document.querySelector(".nav");
let open;
function openMenu() {
if (open) {
menu.style.display = "none";
open = false;
} else if (!open) {
menu.style.display = "block";
open = true;
}
}
.menubar {
width: 100%;
height: 50px;
line-height: 50px;
vertical-align: middle;
background-color: #fff;
border-bottom: 1px solid #f5f5f5;
position: fixed;
top: 0;
-webkit-user-select: all;
user-select: none;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
display: flex;
align-items: center;
padding-left: 15px;
position: absolute;
}
.nav {
display: flex;
font-size: 18px;
flex-direction: row;
list-style: none;
margin: 0 auto;
padding: 0;
}
.nav li {
margin: 0 15px;
}
.hamburger {
margin: 0 13px 0 auto;
height: inherit;
}
#media screen and (min-width: 801px) {
.nav {
display: flex !important;
}
.hamburger {
display: none;
}
}
#media screen and (max-width: 800px) {
.hamburger {
display: flex;
}
.nav {
display: none;
text-align: center;
}
}
<body>
<div class="menubar">
WEBSITE NAME
<ul class="nav">
<li>HOME</li>
<li>MENU1</li>
<li>MENU2</li>
<li>ABOUT</li>
</ul>
<input type="image" class="hamburger" onclick={openMenu()} src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/800px-Hamburger_icon.svg.png" />
</div>
</body>
Accompanying JSFiddle.
You can add a window load and resizing listener. When the window gets smaller than 800px the script will add a class to your element.
I currently have it set to place a class .mobile. Made the necessary stylistic changes to this class for the mobile menu
Add this in your JS code:
window.addEventListener('resize', setMobileClass);
window.addEventListener('load', setMobileClass);
function setMobileClass() {
if (window.innerWidth <= 800) {
menu.classList.add('mobile');
} else {
menu.classList.remove('mobile');
}
};
Add this in your CSS:
.mobile {
position: absolute;
right: 0px;
top: 50px;
}
EXAMPLE:
const menu = document.querySelector(".nav");
let open;
function openMenu() {
if (open) {
menu.style.display = "none";
open = false;
} else if (!open) {
menu.style.display = "block";
open = true;
}
}
window.addEventListener('resize', setMobileClass);
window.addEventListener('load', setMobileClass);
function setMobileClass() {
if (window.innerWidth <= 800) {
menu.classList.add('mobile');
} else {
menu.classList.remove('mobile');
}
};
.menubar {
width: 100%;
height: 50px;
line-height: 50px;
vertical-align: middle;
background-color: #fff;
border-bottom: 1px solid #f5f5f5;
position: fixed;
top: 0;
-webkit-user-select: all;
user-select: none;
display: flex;
align-items: center;
}
.logo {
font-size: 24px;
display: flex;
align-items: center;
padding-left: 15px;
position: absolute;
}
.nav {
display: flex;
font-size: 18px;
flex-direction: row;
list-style: none;
margin: 0 auto;
padding: 0;
}
.nav li {
margin: 0 15px;
}
.hamburger {
margin: 0 13px 0 auto;
height: inherit;
}
#media screen and (min-width: 801px) {
.nav {
display: flex !important;
}
.hamburger {
display: none;
}
}
#media screen and (max-width: 800px) {
.hamburger {
display: flex;
}
.nav {
display: none;
text-align: center;
}
}
.mobile {
position: absolute;
right: 0px;
top: 50px;
}
<div class="menubar">
WEBSITE NAME
<ul class="nav">
<li>HOME</li>
<li>MENU1</li>
<li>MENU2</li>
<li>ABOUT</li>
</ul>
<input type="image" class="hamburger" onclick={openMenu()}
src="https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/800px-Hamburger_icon.svg.png" />
</div>
I found a fitting and elegant solution based on 54ka's answer. Instead of adding a mobile class with extra JS code, I modified screen-size restricted nav class to be the following:
#media screen and (max-width: 800px) {
.hamburger {
display: flex;
}
.nav {
display: none;
position: absolute;
text-align: center;
width: 100%;
right: 0px;
top: 50px;
}
}
This ensured that the menu would appear centered, underneath the menubar. Additional background-color and border commands can be added to clean up the dropdown menu.
I have an issue with the responsive sidebar nav links(anchor tags) won't click
Here is the part of the HTML code
<!-- Nav -->
<nav class="main-nav">
<img src="img/logo-dark-transparent.png" alt="AS Logo" class="logo">
<ul class="main-menu">
<li>Home</li>
<li>About Me</li>
<li>Projects</li>
<li>Contact Me</li>
</ul>
....
</nav>
The main CSS code for navbar is here
.main-nav{
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
padding: 20px 0;
z-index: 1;
/* font-size: 1.5em; */
font-size: clamp(.5rem, .8vw + 1rem, 1.5rem);
}
.main-nav .logo{
width: 110px;
}
.main-nav ul{
display: flex;
}
.main-nav .main-menu li{
padding: 0 2em;
}
.main-nav .main-menu li a{
padding-bottom: 2px;
}
.main-nav .main-menu li a:hover{
border-bottom: 2px solid var(--text-color);
}
The CSS code for side nav is
#media(max-width:700px){
.container{
overflow-x: hidden;
}
section{
height: auto;
}
/* Navbar */
.menu-btn{
display: block;
}
.menu-btn:hover{
opacity: 0.5;
}
.main-nav ul.main-menu{
display: block;
position: absolute;
top: 0;
left: 0;
background: var(--bg-color);
filter: brightness(0.85);
width: 60%;
height: 100%;
opacity: 0.9;
padding: 30px;
transform: translateX(-500px);
transition: transform 0.5s ease;
}
.main-nav ul.main-menu.show{
transform: translateX(-20px);
}
.main-nav ul.main-menu li{
padding: 20px;
}
.main-nav ul.main-menu li:first-child{
margin-top: 2rem;
}
.main-nav ul.right-menu{
margin-right: 60px;
}
But the show class is toggled dynamically by JS code below
//Toggle Menu
const mainMenu = document.querySelector('.main-menu');
document.querySelector('.menu-btn').addEventListener('click', () => {
mainMenu.classList.toggle('show');
})
Also, I wanted to achieve smooth scrolling which works on desktop version but doesn't in the mobile sidebar menu using this JS code snippet
//Vanilla JS Smooth Scroll
document.querySelectorAll('.main-menu a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
I have been debugging for hours with no success, any help or advice would be appreciated.
Maybe the id of div you want to scroll with do not match the link(href) addresses.You need to make sure this. Also, you can do a null check in the JavaScript code as follows.
document.querySelectorAll('.main-menu a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
var elmnt = document.querySelector(this.getAttribute('href'));
if(elmnt != null) {
elmnt.scrollIntoView({
behavior: 'smooth'
});
}
});
});
Add !important in your CSS code
.menu-btn { display: block !important; }
The first html I did was doing fine with its z-index but on the second one, I added sticky nav bar, and now the nav bar isn't showing up when in phone mode.
Here is the comparison:
(sorry for the different sized images)
#navbar {
position: fixed;
top: 0px;
display: flex;
overflow: hidden;
padding: 10px 10px; /* Large padding which will shrink on scroll (using JS) */
transition: 0.4s; /* Adds a transition effect when the padding is decreased */
justify-content: space-around;
align-items: center;
min-height: 8vh;
width: 100%;
background-color: #55426e;
z-index: 4;
}
.sticky{
padding: 5px 10px;
}
.burger {
display: none;
cursor: pointer;
padding: 5px;
z-index: 3;
}
.burger div{
width: 23px;
height: 3px;
background-color: aliceblue;
margin: 5px;
transition: all 0.3s ease;
border-radius:10px;
}
#media screen and (max-width: 1024px) {
.nav-links{
width: 65%;
}
}
#media screen and (max-width: 768px){
body{
overflow-x: hidden;
}
.nav-links {
position: absolute;
right: 0px;
height: 92vh;
top: 8vh;
background-color: #55426e;
display:flex;
flex-direction:column;
align-items: center;
width: 50%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.nav-links li{
opacity: 0;
}
.burger{
display:block;
}
#navbar {
padding: 2px 10px !important;
/* Use !important to make sure that JavaScript
doesn't override the padding on small screens */
}
}
.withpic {
position: relative;
background-image: linear-gradient(rgba(0,0,0,0),rgba(0,0,0,0.5)), url(aboutme2.JPG);
height: 100vh;
background-size: cover;
background-position: center;
}
.wopic {
position: relative;
background-color: #ddd5e2;
padding-top: 20px;
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-around;
padding-left: 50px;
padding-right: 50px;
padding-bottom: 50px;
}
.under {
position: relative;
z-index: 3;
}
/*sticky nav bar -- from w3schools*/
.overtext {
display: flex;
align-items: flex-end;
flex-direction: column;
color: #ddd5e2;
text-align: center;
position: relative;
z-index: -99;
}
<DOCTYPE! html>
<html>
<head>
<title>Website</title>
<link href="ask.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="withpic">
<nav>
<div id="navbar">
<div id="logo">
<h4>logo</h4>
</div>
<ul class="nav-links">
<li> HOME </li>
<li> ABOUT </li>
<li> PHOTOGRAPHY </li>
<li> ORGANIZER </li>
<li> CONTACT </li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</div>
</nav>
<div class="lefty under">
<div class="overtext">
<h1>About Me</h1>
<em>
私について
</em>
</div>
</div>
</div>
<div class="wopic">
<p>section without picture</p>
</div>
<script src="app.js"></script>
<script src="nav.js"></script>
</body>
</html>
//burger javascript
function navSlide() {
let burger = document.querySelector(".burger");
let nav = document.querySelector(".nav-links");
let navLinks = document.querySelectorAll(".nav-links li");
//toggle nav
burger.addEventListener("click", function() {
nav.classList.toggle('nav-active');
//animate links
navLinks.forEach((link, index)=> {
if (link.style.animation) {
link.style.animation = "";
} else {
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7 + 0.5}s`;
}
});
//burger animation
burger.classList.toggle('toggle');
});
}
navSlide();
//sticky nav bar with transitions javascript
// When the user scrolls down 80px from the top of the document, resize the navbar's padding and the logo's font size
window.onscroll = function () { scrollFunction() };
function scrollFunction() {
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
document.getElementById("navbar").style.padding = "2px 10px";
document.getElementById("logo").style.fontSize = "20px";
} else {
document.getElementById("navbar").style.padding = "10px 10px";
document.getElementById("logo").style.fontSize = "25px";
}
}
I deleted some font properties in css to avoid it getting longer. Please tell me if I need to add some more css from my original code.
Here's an updated snippet with the visibility issue fixed. There must be additional css that you didn't include above, but the main idea is here. Click the hamburger menu and the nav bar appears.
Two main problems I saw:
An overflow: hidden on the #nav
No transform: translateX(0) to bring the nav menu into position.
function navSlide() {
let burger = document.querySelector(".burger");
let nav = document.querySelector(".nav-links");
let navLinks = document.querySelectorAll(".nav-links li");
//toggle nav
burger.addEventListener("click", function() {
nav.classList.toggle('nav-active');
//animate links
navLinks.forEach((link, index) => {
if (link.style.animation) {
link.style.animation = "";
} else {
link.style.animation = `navLinkFade 0.5s ease forwards ${index / 7 + 0.5}s`;
}
});
//burger animation
burger.classList.toggle('toggle');
});
}
navSlide();
//sticky nav bar with transitions javascript
// When the user scrolls down 80px from the top of the document, resize the navbar's padding and the logo's font size
window.onscroll = function() {
scrollFunction()
};
function scrollFunction() {
if (document.body.scrollTop > 80 || document.documentElement.scrollTop > 80) {
document.getElementById("navbar").style.padding = "2px 10px";
document.getElementById("logo").style.fontSize = "20px";
} else {
document.getElementById("navbar").style.padding = "10px 10px";
document.getElementById("logo").style.fontSize = "25px";
}
}
:root,
html,
body {
height: 100%;
width: 100%;
}
#navbar {
position: fixed;
top: 0px;
display: flex;
padding: 10px 10px;
/* Large padding which will shrink on scroll (using JS) */
transition: 0.4s;
/* Adds a transition effect when the padding is decreased */
justify-content: space-around;
align-items: center;
min-height: 8vh;
width: 100%;
background-color: #55426e;
z-index: 4;
}
.sticky {
padding: 5px 10px;
}
.burger {
display: none;
cursor: pointer;
padding: 5px;
z-index: 3;
}
.burger div {
width: 23px;
height: 3px;
background-color: aliceblue;
margin: 5px;
transition: all 0.3s ease;
border-radius: 10px;
}
#media screen and (max-width: 1024px) {
.nav-links {
width: 65%;
}
}
#media screen and (max-width: 768px) {
body {
overflow-x: hidden;
}
.nav-links {
position: absolute;
right: 0px;
height: 92vh;
top: 8vh;
background-color: #55426e;
display: flex;
flex-direction: column;
align-items: center;
width: 50%;
transform: translateX(100%);
transition: transform 0.5s ease-in;
}
.nav-links li {
opacity: 0;
}
.burger {
display: block;
}
.nav-links.nav-active {
transform: translateX(0);
display: flex;
flex-direction: column;
justify-content: space-around;
}
.nav-links.nav-active li,
.nav-links.nav-active li a {
list-style: none;
opacity: 1;
color: white;
text-decoration: none;
}
#navbar {
overflow: visible;
padding: 2px 10px !important;
/* Use !important to make sure that JavaScript
doesn't override the padding on small screens */
}
}
.withpic {
position: relative;
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5)), url(aboutme2.JPG);
height: 100vh;
background-size: cover;
background-position: center;
}
.wopic {
position: relative;
background-color: #ddd5e2;
padding-top: 20px;
display: flex;
align-items: center;
flex-direction: column;
justify-content: space-around;
padding-left: 50px;
padding-right: 50px;
padding-bottom: 50px;
}
.under {
position: relative;
z-index: 3;
}
/*sticky nav bar -- from w3schools*/
.overtext {
display: flex;
align-items: flex-end;
flex-direction: column;
color: #ddd5e2;
text-align: center;
position: relative;
z-index: -99;
}
<DOCTYPE! html>
<html>
<head>
<title>Website</title>
<link href="ask.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="withpic">
<nav>
<div id="navbar">
<div id="logo">
<h4>logo</h4>
</div>
<ul class="nav-links">
<li> HOME </li>
<li> ABOUT </li>
<li> PHOTOGRAPHY </li>
<li> ORGANIZER </li>
<li> CONTACT </li>
</ul>
<div class="burger">
<div class="line1"></div>
<div class="line2"></div>
<div class="line3"></div>
</div>
</div>
</nav>
<div class="lefty under">
<div class="overtext">
<h1>About Me</h1>
<em>
私について
</em>
</div>
</div>
</div>
<div class="wopic">
<p>section without picture</p>
</div>
<script src="app.js"></script>
<script src="nav.js"></script>
</body>
</html>
so I'm having issues with closing my mobile nav hamburger menu when a link is clicked. Only my top link is clickable right now just FYI.
The answer is on the tip of my tongue but I'm not quite there. I think mainly it's a syntax issue on my end. So yes the menu on mobile opens and closes when clicking the menu, but it doesn't close when a link is clicked.
I've looked all over, but all I could find were jQuery answers.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="css\style.css">
<title>eddiepearsonUX</title>
</head>
<body>
<nav>
<div class="hamburger">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
<ul class="nav-links">
<li>Audio UX Study</li>
<li>Web App UX</li>
<li>Contact</li>
</ul>
</nav>
<section class="intro-section">
<h1 class="name">
<span>eddie</span>
<span>Pearson</span>
</h1>
<h3 class="intro">
<p>Audio<br>and Visual</p>
<p>UX</p>
</h3>
</section>
<h3 class="content-title">
<p>Audio UX Study</p>
</h3>
<ul style="list-style-type: none" id="Audio-UX-Study"class="content">
<li class="main-img"><img src="https://www.dl.dropboxusercontent.com/s/rktj2nhj07l2ne7/20191206-Screenshot%20%28223%29.jpg?dl=0" alt="Ableton screen with wavforms and effects stack"></li>
<li class="second-img"><img src="https://www.dl.dropboxusercontent.com/s/j1aipb71ccj3o64/Screenshot%20%28225%29.png?dl=0" alt="Wavforms from audio"></li>
<li class="copy">
</li>
<li class="main-img"></li>
<li class="second-img"></li>
<li class="copy">
</li>
</ul>
<script src="js\app.js"></script>
</body>
</html>
#import url('https://fonts.googleapis.com/css?family=Merriweather:300,700&display=swap');
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: 'Merriweather', serif;
}
body {
font-family: sans-serif;
background-color: #e6e6e0;
}
/* NAVIGATION */
nav {
height: 10vh;
background: #e6e6e0;
/* position: sticky; */
}
.name-div {
position: absolute;
width: 50%;
top: 1.8rem;
left: 2rem;
}
.name {
color: rgb(82, 82, 56);
font-size: calc(0.2rem + 1.1rem);
}
.nav-links {
display: flex;
position: relative;
list-style: none;
max-width: 75vw;
height: 100%;
justify-content: end;
align-items: center;
margin: auto;
}
.nav-links li a {
color:rgb(82, 82, 56);
font-weight: bold;
text-decoration: none;
font-size: 18px;
padding-left: 1em;
}
#media screen and (max-width: 768px) {
.nav-links {
position: fixed;
background: #e6e6e0;
height: 100vh;
width: 100%;
flex-direction: column;
justify-content: space-around;
margin-left: auto;
clip-path: circle(100px at 90% -20%);
-webkit-clip-path: circle(100px at 90% -10%);
transition: all 1s ease-out;
pointer-events: none;
}
.nav-links.open {
clip-path: circle(1100px at 90% -10%);
-webkit-clip-path: circle(1100px at 90% -10%);
pointer-events: all;
max-width: 95%;
}
.line {
width: 30px;
height: 3px;
background: rgb(82, 82, 56);
margin: 5px;
}
nav {
position: relative;
}
.hamburger {
position: absolute;
cursor: pointer;
right: 5%;
top: 50%;
transform: translate(-5%, -50%);
z-index: 2;
}
.nav-links li {
opacity: 0;
}
.nav-links a {
font-size: 25px;
}
.nav-links li:nth-child(1) {
transition: all 0.5s ease 0.1s;
}
.nav-links li:nth-child(2) {
transition: all 0.5s ease 0.2s;
}
.nav-links li:nth-child(3) {
transition: all 0.5s ease 0.3s;
}
.nav-links li:nth-child(4) {
transition: all 0.5s ease 0.4s;
}
li.fade {
opacity: 1;
}
}
/* INTRO SECTION */
.intro-section {
max-width: 75vw;
margin: auto;
/* background-color: #fff; */
}
.intro-section .name {
padding: 2rem 0 2rem 0rem;
font-size: calc(0.8rem + 3vw);
}
.intro-section .name span:nth-of-type(1) {
color: rgb(174, 177, 156);
}
.intro {
color:rgb(174, 177, 156);
font-size: calc(0.6rem + 2vw);
}
.intro p:nth-of-type(2) {
font-size: calc(0.6rem + 3vw);
color:rgb(82, 82, 56);
}
/* CONTENT SECTION */
.content-title {
display: block;
margin: auto;
margin-top: 5rem;
margin-bottom: 2rem;
max-width: 75vw;
font-size: calc(0.6rem + 1vw);
color:rgb(82, 82, 56);
}
.content {
max-width: 75vw;
margin: 3rem auto;
display: grid;
width: 100%;
height: auto;
display: grid;
margin-bottom: 3em;
grid-gap: 1em;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: minmax(100px, auto);
}
.main-img {
grid-column: 1 / 2;
}
.content > li > img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');
const links = document.querySelectorAll('.nav-links li');
const whatever = document.querySelectorAll('.nav-links li a');
hamburger.addEventListener('click', () => {
navLinks.classList.toggle('open');
links.forEach(link => {
link.classList.toggle('fade');
});
});
The only thing you're listening for clicks on is the hamburger element.
Try adding a listener on the navLinks element, like so:
const hamburger = document.querySelector('.hamburger');
const navLinks = document.querySelector('.nav-links');
const links = document.querySelectorAll('.nav-links li');
const whatever = document.querySelectorAll('.nav-links li a');
hamburger.addEventListener('click', () => {
navLinks.classList.toggle('open');
links.forEach(link => {
link.classList.toggle('fade');
});
});
navLinks.addEventListener('click', () => {
navLinks.classList.toggle('open')
links.forEach(link => {
link.classList.toggle('fade');
});
})
There might be more tweaks you need to make, but this should get you started.
I have a sidebar that slides out 250px using javscript on the desktop view. When it comes to the mobile view I want the sidebar to take up 100% width. I am trying to use Media Queries in Javascript but no matter what changes I make It seems to overwrite my styles I have for my sidebar on the desktop view.
HTML
<nav class="navbar">
<div id="toggle-btn" class="sidemenu-btn">
<i class="fas fa-bars"></i>
</div>
<div id="toggle-nav" class="navbar-items animated fadeInLeft delay-1s">
Home
About
Skills
Portfolio
Contact
</div>
</nav>
CSS
.navbar {
height: 100%;
width: 0;
position: fixed;
background: #141313;
}
.navbar .sidemenu-btn {
font-size: 2.5rem;
padding: 3rem 0;
text-align: center;
margin-left: 1rem;
cursor: pointer;
color: #141313;
}
.navbar .navbar-items {
display: flex;
flex-direction: column;
text-align: center;
display: none;
margin-left: 1rem;
}
.navbar .navbar-items a {
text-decoration: none;
color: white;
padding: 1.2rem 0;
font-weight: 400;
font-size: 1.2rem;
text-transform: uppercase;
}
.navbar .navbar-items a:hover {
text-decoration: line-through;
}
#media screen and (max-width: 768px) {
.navbar {
position: relative;
}
}
JS
const toggleBtn = document.querySelector("#toggle-btn");
const toggleNav = document.querySelector(".navbar");
const togglenavItems = document.querySelector('.navbar-items');
toggleBtn.addEventListener("click", sideMenu);
toggleBtn.addEventListener("click", mediaQuery);
function sideMenu() {
if (toggleNav.style.width === "250px") {
toggleNav.style.width = "0px";
} else {
toggleNav.style.width = "250px";
}
}
function mediaQuery() {
const x = window.matchMedia('(max-width: 768px)');
const y = document.querySelector('.navbar');
if (x.matches && y.style.width === "100%") {
y.style.width = "0px";
} else {
y.style.width = "100%";
}
}
Media queries can do the work. You don't need js for changing the width of the navbar-items. See this
const toggleBtn = document.querySelector("#toggle-btn");
const toggleNav = document.querySelector(".navbar");
const togglenavItems = document.querySelector('.navbar-items');
toggleBtn.addEventListener("click", sideMenu);
function sideMenu() {
toggleNav.classList.toggle('open');
}
* {
box-sizing: border-box;
}
body {
margin: 0;
}
.navbar {
height: 100%;
width: 100%;
position: fixed;
}
.sidemenu-btn {
font-size: 2.5rem;
padding: 0;
text-align: center;
cursor: pointer;
color: green;
position: absolute;
right: 20px;
top: 20px;
}
.navbar-items {
display: flex;
flex-direction: column;
text-align: center;
width: 250px;
height: 100%;
padding-left: 1rem;
background: #141313;
transition: all .5s ease;
}
.navbar .navbar-items a {
text-decoration: none;
color: white;
padding: 1.2rem 0;
font-weight: 400;
font-size: 1.2rem;
text-transform: uppercase;
}
.navbar .navbar-items a:hover {
text-decoration: line-through;
}
#media (max-width: 768px) {
.navbar-items {
width: 100%;
}
}
.navbar.open .navbar-items {
width: 0;
}
<nav class="navbar">
<div id="toggle-btn" class="sidemenu-btn">
<i class="fas fa-bars"></i>
Toggle
</div>
<div id="toggle-nav" class="navbar-items animated fadeInLeft delay-1s">
Home
About
Skills
Portfolio
Contact
</div>
</nav>
Just adding the media query you can change the width of the element, no need to check in js
#media (max-width: 768px) {
.navbar-items {
width: 100%;
}
}
Adding a .open class that will be added on the .navbar and will trigger the transition
.navbar.open .navbar-items {
width: 0;
}
Your js was now simplified
const toggleBtn = document.querySelector("#toggle-btn");
const toggleNav = document.querySelector(".navbar");
toggleBtn.addEventListener("click", sideMenu);
function sideMenu() {
toggleNav.classList.toggle('open');
}
This is easier done with CSS to control how it looks on the mobile/desktop, with JS just handling the logic. The following will fix the style discrepancy, and make your JS easier to navigate.
CSS
.navbar{
width: 250px;
height: 100%;
position: fixed;
background: #141313;
}
.navHidden{
width: 0px !important;
}
/* smaller screen size */
#media screen and (max-width:768px) {
.navbar{
width: 100%;
}
}
HTML
<nav class="navbar navHidden">
JS
function sideMenu() {
toggleNav.classList.toggle("navHidden")
}
Sidenote
In your included code, the click of your toggle button you will be setting the width of the navbar to 250px, but then it will be passed through to your next function, which will then swap it to 100% in EVERY CASE regardless of screen size, so the toggle function you have written will never work.