I want the navbar to disappear when it reaches 768px and become a button on the right side. The button will open the navbar back, I have added code to make the navbar to disappear at 768px but it doesn't work. Not so sure what is wrong since the button shows 768px. But the navbar does not disappear at 768px.
html
<nav id="Nav" class="navbar nav">
<div class="container flex">
<img src="Week5saasappassets-210323-142515 (1)/Week-5-saas-app-assets/project_logo/logo.svg" alt="Company logo" class="company-logo">
<button class="navbar-toggler" aria-expanded="false" aria-controls="navbarDropdown"><span>☰</span></button>
<div class="nav-parent">
<ul class="navbar-nav">
<li class="nav-link">
Home
</li>
<li class="nav-link">
Features
</li>
<li class="nav-link">
Learn
</li>
<li class="nav-link">
Price
</li>
<li class="nav-link">
Hire us
</li>
</ul>
</div>
</div>
</nav>
css
navbar-toggler{
position: absolute;
right: var(--size-20);
outline: none;
background-color: transparent;
border: 1px solid transparent;
}
.navbar-toggler span{
color: var(--pureblack);
font-size: var(--size-20);
}
[aria-controls="navbarDropdown"]{
display: none;
}
.navbar .container{
top: 0;
right: 0;
left: 0;
z-index: 500;
transition: ease-in-out 0.3s;
display:flex;
align-items: center;
}
.navbar-brand{
cursor: pointer;
}
.nav-parent{
margin-left: auto;
}
.navbar-nav{
display: flex;
align-items: center;
}
.navbar-nav li{
align-items: center;
}
.nav-link a{
margin-right: 2.5rem;
}
responsive
#media screen and (max-width: 768px) {
[aria-controls="navbarDropdown"] {
display: block;
}
[aria-expanded="false"] ~ ul{
display: none;
}
[aria-expanded="true"] ~ ul{
display: block;
}
}
javascript
<script>
const navButton = document.querySelector('button[aria-expanded]');
function toggleNav({ target }){
const expanded = target.getAttribute('aria-expanded') === 'true' || false;
navButton.setAttribute('aria-expanded', !expanded);
}
navButton.addEventListener('click', toggleNav);
</script>
Your css to select the ul via the button,
[aria-expanded="false"] ~ ul{
display: none;
}
[aria-expanded="true"] ~ ul{
display: block;
}
Won't work, here's why. The tilde (~) is a sibling selector. For this selector to work the way you specified, your ul would have to appear after the button, within the same container, like this:
<button ariaexpanded="true"></button>
<ul class="navbar-nav">
<li class="nav-link">
Home
</li>
</ul>
So if your .nav-parent div isn't being used, you could try remove that and it will likely work.
This is my approach when doing mobile menus. Have your media query target a certain container which goes to 100% viewport width and height at your mobile breakpoint. It should also be offset vertically or horizontally out of the view of the user. Then you just need some JS to toggle a 'showing' class which positions the menu on the user's screen:
Your toggle nav function:
function toggleNav({ target }){
const expanded = target.getAttribute('aria-expanded') === 'true' || false;
navButton.setAttribute('aria-expanded', !expanded);
// Toggle nav 'showing' class
if (nav.classList.contains('showing')) {
nav.classList.remove('showing')
} else {
nav.classList.add('showing')
}
}
// Close menu button
closeNavButton.addEventListener('click', () => {
nav.classList.remove('showing')
})
CSS:
/* Don't show the 'close' button on desktop */
.nav-parent button {
display: none;
}
/* Mobile breakpoint */
#media screen and (max-width: 768px) {
[aria-controls="navbarDropdown"] {
display: block;
}
[aria-expanded="false"] ~ ul{
display: none;
}
/* Your menu now takes up 100% of screen, and is offset to the left */
.nav-parent {
opacity: 0;
position: absolute;
height: 100vh;
width: 100vw;
top: 0;
left: -100vw;
transition: all 0.25s ease;
background: white;
}
/* When the showing class is added, it will position itself on the screen */
.nav-parent.showing {
opacity: 1;
left: 0;
}
}
HTML (add a close-menu button)
<div class="nav-parent">
<button>
Close
</button>
<ul class="navbar-nav">
...
</div>
JSfiddle demo
There's lots of room for creativity.
Related
I am trying to make a responsive navigation on my Wordpress site where I am building a template from scratch. I have decent experience with HTML and CSS(SCSS) some PHP but not so much Javascript or the Wordpress way.
I am looking to remove the :hover element on my sub menu under the 'services' li and instead have it trigger on click on tablet and mobile devices. I understand it will be similar to how I have done the mobile menu button but I am struggling to figure out the best way to do it.
Can anyone give me an idea please? Thanks in advance.
function myFunction() {
var x = document.getElementById("myDIV");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
header {
height: 128px;
border-bottom: 1px solid #f0f0f0;
width: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 4000;
background: white;
}
header .nav-container {
max-width: 100em;
margin: auto;
display: flex;
justify-content: space-between;
z-index: 45;
padding: 0 1.5rem;
}
header .nav-container .logo {
width: 14%;
padding-top: 2.8rem;
}
header .nav-container p {
display: none;
}
#media only screen and (max-width: 600px) {
header .nav-container p {
display: flex;
}
}
header .nav-container nav {
padding-top: 2rem;
}
#media only screen and (max-width: 600px) {
header .nav-container nav {
display: none;
}
}
#media only screen and (max-width: 600px) {
header .nav-container nav ul {
flex-direction: column;
display: flex;
}
}
header .nav-container nav ul li {
position: relative;
display: inline-block;
}
header .nav-container nav ul li a {
display: inline-block;
transition: all 0.5s linear;
text-decoration: none;
padding: 16px 10px;
color: #00458B;
}
header .nav-container nav ul li a:hover {
color: #00458B;
}
header .nav-container nav ul li ul {
display: none;
background: white;
position: absolute;
top: 100%;
width: 160px;
padding: 0;
z-index: 500;
}
header .nav-container nav ul li ul li, header .nav-container nav ul li ul a {
width: 100%;
}
header .nav-container nav ul li:hover ul {
display: block;
}
header .nav-container nav ul .menu-item-40 a {
padding: 0;
}
<header>
<div class="nav-container">
<p onclick="myFunction()"> Click</p>
<nav class="nav" role="navigation" id="myDIV">
<ul>
<li class="nav-item">Home
</li>
<li class="nav-item">About us
</li>
<li class="nav-item">Services
<ul class="sub-menu">
<li class="nav-item ">Windows
</li>
<li class="nav-item">Glass
</li>
<li class="nav-item">Doors
</li>
<li class="nav-item">Roofline
</li>
</ul>
</li>
<li class="nav-item">Our Work
</li>
<li class="nav-item">Contact Us
</li>
</ul>
</nav>
</div>
</header>
Wrap it with Media Query so it doesn't work on Mobile and tablet.
header .nav-container nav ul li:hover ul {
display: block;
}
This is only one of many possible solutions, but I think it gives you an idea off how to solve the problem.
First you have to wrap following selector with a media query to disable the hover when your mobile button shows up. In your case it would look like this:
#media only screen and (min-width: 601px) {
header .nav-container nav ul li:hover ul {
display: block;
}
}
To attach the toggle functionality I would suggest to add a js-submenu-toggle class to all a elements which have a submenu as sibling. I prefer to add a js prefix to my classes to mark them as classes that are only used in combination with javascript and have no styling attached to them:
<ul>
...
<li class="nav-item">
Services
<ul class="sub-menu">
...
</ul>
</li>
...
</ul>
For the actual functionality use the toggle function to add and remove an is-active class on click to the submenu element and the matchMedia function to make the toggle functionality only available when your mobile menu button is visible:
document.addEventListener('click', event => {
const element = event.target;
const mediaQuery = window.matchMedia('(max-width: 600px)');
if(element.matches('.js-submenu-toggle') && mediaQuery.matches) {
// Prevents the default behaviour of the `a`-tag with an `href`-attribute
event.preventDefault();
element.nextElementSibling.classList.toggle('is-active');
}
});
The is-active class should look like this:
.is-active {
display: block;
}
Here is the snippet:
const exitBtn = document.querySelector('#exitBtn');
menuBtn.addEventListener('click', () => {
const menu = document.querySelectorAll('.menu');
for (let el of menu) {
el.style.display = 'block'
}
})
#media (max-width: 934px) {
.max-width {
padding: 0 50px;
}
.fa.fa-bars.menuBtn {
display: block;
}
.menu {
position: fixed;
height: 100vh;
width: 100%;
left: 0;
top: 0;
background-color: #111;
text-align: center;
padding-top: 110px;
}
.exit {
z-index: 999;
display: none;
margin: 1.8rem;
}
.menu ul li {
display: block;
}
.menu li a {
display: inline-block;
margin: 20px 0;
font-size: 35px;
}
}
<header>
<nav class="navbar" id="nav">
<div class="max-width">
<div class="logo"><a id="headSpan" href="index.html">Port<span>folio.</span></a></div>
<div class="menu">
<ul>
<li>Home</li>
<li>About</li>
<li>Skills</li>
<li>Projects</li>
<li>CV</li>
<li>Contact</li>
</ul>
</div>
<div>
<i class="fa fa-bars menuBtn" id="menuBtn" aria-hidden="true"></i>
</div>
<div class="exit">
<i class="fa fa-times-circle exit" id="exitBtn" aria-hidden="true"></i>
</div>
</div>
</nav>
I tried making it block but it did not work, I also tried making flex-direction to be column but still did not work. Am I doing something wrong somewhere? What is causing the issue of the menu not being displayed from up to down? Is there an alternative way to go about this?
Maybe try to set the position of the navbar class to fixed if it is a sidebar you are trying to do, or as how I perceive, you are trying to make a menu bar on the side supposedly and not a rowline. Then the class of menu should be the one flexed and not fixed. You are supposed to make a container for the menu that is the fixed one so that all of its content will be fixed on the side. Show me more of the css and I might help. But try doing
.navbar{
width: width;
height: 100vh;
position: fixed;}
Then the "max-width" class will have the flex attribute
.max-width{
display: flex;
flex-direction: column;}
For my webpage (Github Page), I want to make my menu sensible to the size of the screen, such that it collapses when they are too small and the elements do not fit. I am planning to add the following solution: w3schools, using a "burguer" icon to join all the elements when the screens are small.
I am able to create the menu with the different elements, to add the "burguer" icon, and then to hide it by default when the screen is big. However, the media queries and the js function must be wrong, because when I do my screen small, the "burguer" icon appears, but the other elements do not dissapear, and cliking on the "burguer" does nothing. I guess there is a mistakes or confussion with the id names somewhere. Could it be?
In the example from w3schools uses the div tab, but I am not. Is it indispensable for the example to work?
/* Toggle between adding and removing the "responsive" class to topnav when the user clicks on the icon */
function myFunction() {
var x = document.getElementById("nav");
if (x.className === "header_nav") {
x.className += " responsive";
} else {
x.className = "header_nav";
}
}
/* Header_nav ----- DRAFT */
#page-wrapper {
padding-top: 3.5em;
}
#header_nav {
background: rgba(0, 0, 0, 0);
box-shadow: 0 0 0.25em 0 rgba(0, 0, 0, 0);
cursor: default;
height: 3.5em;
left: 0;
line-height: 3.5em;
position: absolute;
top: 0;
width: 100%;
z-index: 100;
}
#header_nav .icon {
display: none;
}
#header_nav h1 {
height: inherit;
left: 1.25em;
line-height: inherit;
margin: 0;
position: absolute;
top: 0;
}
#header_nav nav {
position: absolute;
right: 1em;
top: 0;
}
#header_nav nav ul {
margin: 0;
}
#header_nav nav ul li {
display: inline-block;
margin-left: 1em;
}
#header_nav nav ul li a,
#header_nav nav ul li span {
border: 0;
color: inherit;
display: inline-block;
height: inherit;
line-height: inherit;
outline: 0;
}
#header_nav nav ul li a.button,
#header_nav nav ul li span.button {
height: 2em;
line-height: 2em;
padding: 0 1.25em;
}
#header_nav nav ul li a:not(.button):before,
#header_nav nav ul li span:not(.button):before {
margin-right: 0.5em;
}
#header_nav nav ul li.active>a,
#header_nav nav ul li.active>span {
color: #e44c65;
}
#header_nav nav ul li>ul {
display: none;
}
body.landing #page-wrapper {
padding-top: 0;
}
body.landing #header_nav {
background: transparent;
box-shadow: none;
position: absolute;
}
/* When the screen is less than 600 pixels wide, hide all links, except for the first one ("Home"). Show the link that contains should open and close the topnav (.icon) */
#media screen and (max-width: 600px) {
#header_nav a:not(:first-child) {
display: none;
}
#header_nav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
#media screen and (max-width: 600px) {
#header_nav.responsive {
position: relative;
}
#header_nav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
#header_nav.responsive a {
float: none;
display: block;
text-align: left;
}
}
<html>
<head>
<title>Eduardo Alvarado</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<link rel="stylesheet" href="assets/css/main.css" />
<noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
<!-- Load an icon library to show a hamburger menu (bars) on small screens -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body class="is-preload">
<!-- Header Navigation Menu -->
<section id="header_nav">
<nav id="nav">
<ul>
<li>
<a href="index">
<p style="color:white">Home</p>
</a>
</li>
<li>
<a href="">
<p style="color:white">Research</p>
</a>
</li>
<li>
<a href="">
<p style="color:white">Game-dev</p>
</a>
</li>
<li>
<a href="photography">
<p style="color:white">Photography</p>
</a>
</li>
<li><i class="fa fa-bars"></i></li>
</ul>
</nav>
</section>
The whole code can be found in the repo (Github Repo).
Can you see maybe the error that I am not able to spot? Why the example from w3school is not applicable?
I would really appreciate your help here. Thank you very much in advance!
Here's a small reproducible solution based on your code:
https://jsfiddle.net/hneromu4/5/
I added a class fixed to the link elements that were supposed to stay when we resized the window:
<section id="header_nav">
<nav id="nav">
<ul>
<li class="fixed">Home</li>
<li>Research</li>
<li>Game-dev</li>
<li>Photography</li>
<li class="fixed hamburguer"><i class="fa fa-bars"></i></li>
</ul>
</nav>
</section>
I also tweaked your css and js.
In your CSS and HTML I have made some alterations as your hamburger menu was inside the same thing which you were trying to hide which is not really a good idea I have also adjusted your CSS slightly as you were setting a position to relative but not setting display to block. Hope this helps!
CSS (line 2525 - 2547):
#media screen and (max-width: 600px) {
#nav {display: none;}
#header_nav a.icon {
float: right;
display: block;
}
}
/* The "responsive" class is added to the topnav with JavaScript when the user clicks on the icon. This class makes the topnav look good on small screens (display the links vertically instead of horizontally) */
#media screen and (max-width: 600px) {
#nav.responsive {position: relative;display: block;}
#header_nav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
#nav.responsive a {
float: none;
display: block;
text-align: left;
}
}
HTML:
<!-- Header Navigation Menu -->
<section id="header_nav">
<a class="icon" onclick="myFunction()"><i class="fa fa-bars"></i></a><nav id="nav" class="header_nav">
<ul>
<li><p style="color:white">Home</p></li>
<li><p style="color:white">Research</p></li>
<li><p style="color:white">Game-dev</p></li>
<li><p style="color:white">Photography</p></li>
</ul>
</nav>
</section>
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.
I have set up a hamburger menu with a close icon already. I'm just not sure how to just turn off the hamburger menu with a simple click. Only thing I've been able to do is just reload the page completely. Perhaps there is some jquery that could be used to solve this issue.
The close menu button is item 1 in the menu list.
Here is my code.
<div class="menu-wrapper">
<nav>
<ul class="header-menu">
<li><i class="far fa-window-close"></i></li>
<li class="current">Home</li>
<li>Prints</li>
<li>Blog</li>
<li>Tutorials</li>
<li>Sports</li>
</ul>
</nav>
</div>
CSS:
#menu-icon {
display: hidden;
width: 40px;
height: 40px;
background: url(../img/menu-icon.png) center;
text-decoration: none;
}
#close-menu {
display: none;
}
#media only screen and (max-width: 600px) {
#menu-icon {
display:inline-block;
z-index: 10000;
}
#close-menu {
display: inline-block;
color: black !important;
font-size: 20px !important;
}
OK, here's an example of how to make a burger nav. Fiddle
HTML:
<nav data-state=closed>
<a>×</a>
<a href=something.html>Link 1</a>
<a href=something-else.html>Link 2</a>
<a href=etc.html>Link 3</a>
</nav>
See how we're preparing to toggle the open/closed state with a data attribute. (We could have used a class, but I prefer a DA in this case because it means we can toggle it; with a class, you'd have to remove one class and add anothe, e.g. remove 'closed' and add 'open'.)
The structure is simple; we use a nav element and use the first a within it as the close icon. We use the multiplication (times) entity for this.
CSS:
nav {
position: absolute;
right: 1rem;
top: 2rem;
padding: 1rem;
background-color: #d55 !important;
}
nav[data-state=closed] {
cursor: pointer;
background: url('https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Hamburger_icon.svg/220px-Hamburger_icon.svg.png') no-repeat 100%/100%;
width: 50px;
height: 50px;
}
nav a { display: block; }
nav a:not(:first-of-type) { border-bottom: solid 1px rgba(0, 0, 0, .2); padding: .8rem 0; }
nav[data-state=closed] * { display: none; }
nav a:first-of-type {
position: absolute;
right: .2rem;
top: -.1rem;
font-size: 2rem;
cursor: pointer;
font-weight: bold;
}
Now here's the key part, the JS:
//get nav element
let nav = $('nav');
//listen for clicks on it
nav.on('click', evt => {
//...get current state (open vs. closed)
let curr_state = nav.attr('data-state');
//...if open, and click was NOT to close icon (first A tag) ignore click
if (curr_state == 'open' && !$(evt.target).is('a:first-of-type')) return;
//...otherwise toggle state (open it or close it)
nav.attr('data-state', curr_state == 'closed' ? 'open' : 'closed');
})