CSS - Create responsive top navigation menu - javascript

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>

Related

How to stop :hover and have onClick on navigation sub menu

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;
}

Responsive top navigation menu: hamburger not displayed on small screen except on home page

I'm using the W3Schools' responsive top menu. When I shrink the browser window the 'hamburger' menu displays and works on the home page, but not on any of the other four pages.
This is the html code:
<
div class="topnav" id="myTopnav">
<a href="index.html" class="active" title="Applied Ecosystem
Services, LLC | Providing essential
environmental services">Home</a>
<a href="testimonials.html" class="active" title="Client Testimonials">Why
Clients Retain Me</a>
<a href="capabilities.html" class="active" title="Providing essential environmental
services">Capabilities</a>
<a href="library.html" class="active" title="Environmental Regulatory Science
Resource Library">Documents</a>
<a href="contact.html" class="active" title="Contacting The Environmental Issues
Doctor">Contact me</a>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
This is the CSS code:
/* Add a black background color to the top navigation */
.topnav {
background-color: #333;
/* background-color: #008B8B */
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
/* Add an active class to highlight the current page */
.topnav a.active {
background-color: #04AA6D;
color: white;
}
/* Hide the link that should open and close the topnav on small screens */
.topnav .icon {
display: none;
}
/* 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) {
.topnav a:not(:first-child) {display: none;}
.topnav 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) {
.topnav.responsive {position: relative;}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
And this is the javascript:
/* Toggle between adding and removing the "responsive" class to topnav when
* the user clicks on the icon */
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
I don't know enough to find why the hamburger menu doesn't display and work on all pages. I look forward to learning why.

mobile navbar not collapsing

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.

Making a Responsive Navigation Bar with content on the left, middle and right

I am trying to make a navigation bar that has content at the left, middle and right of the navigation bar. All these while ensuring the nav bar is still responsive. When page is minimised, a drop down menu pops out. Moreover, I am barred from using bootstrap (Homework). So how do I do it without relying on other CSS. Basically How do I create it?
I tried reading up bootstraps codes but I do not understand. Relatively rookie in terms of coding
Retrieved from W3schools
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #333;
}
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav a.active {
background-color: #4CAF50;
color: white;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 600px) {
.topnav a:not(:first-child) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
#media screen and (max-width: 600px) {
.topnav.responsive {
position: relative;
}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="topnav" id="myTopnav">
Home
News
Contact
About
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<div style="padding-left:16px">
<h2>Responsive Topnav Example</h2>
<p>Resize the browser window to see how it works.</p>
</div>
So what I am trying to achieve is to make "home" on the most left of the nav bar, the "news", "content" on the center of the nav bar and lastly. The "about" on the most right of the nav bar. I want the bar to have all mentioned while still keeping the responsive function with menu when minimised.
I would use flexbox: (guide on css-tricks) - it's widely supported and easy to use.
To start using flexbox, you have to add display: flex property on the parent element (.topnav) and justify-content: space-between to have child elements distributed equally on the top navbar. It will look like this:
Now, you should just group elements to three groups: left, center, right. Of course, if there is only one element on the left and right, group is needed only for middle elements (so flexbox will treat them as one child).
Something unrelated to your question: try to use more semantic HTML elements, for example, I've changed the div containing navigation links to a nav element: mdn on nav element.
JSFiddle

W3 Responsive Navbar Won't Work for My Application

For some reason the starter code from W3 for setting up a responsive nav bar is not working for my website. I am trying to follow https://www.w3schools.com/howto/howto_js_topnav_responsive.asp . My navbar is structured a bit different than theirs. Mine has nav tags, ul and li tags. I'm thinking it has something to do with how I'm navigating the DOM but I'm just not able to get it. Any help would be appreciated.
I've already tried changing the media queries to be .topnav ul li a instead of just .topnav a but that doesn't work either.
<div id="header">
<div id="logo">
<img id="logo" src="your-choice-logo.jpg">
</div>
<nav class="topnav" id="myTopNav">
<ul>
<li><a class="active" href="#welcome-section">Home</a></li>
<li>Make Appointment</li>
<li>Contact Us</li>
<li>Services</li>
<li>Gallery</li>
<li>Reviews</li></li>
<li>Areas Served</li>
<li>Facebook</li>
<li><a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i></li>
</a>
</ul>
</nav>
</div>
/* 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) {
.topnav ul li a:not(:first-child) {display: none;}
.topnav 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) {
.topnav.responsive {position: relative;}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive ul li a {
float: none;
display: block;
text-align: left;
}
}
/* Hide the link that should open and close the topnav on small
screens */
.topnav .icon {
display: none;
}
/* Toggle between adding and removing the "responsive" class to
topnav when the user clicks on the icon */
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
You have several issues here.
You have problems with html tags (some of them closing before the nested tag is closed).
For some styles you should use li (display/position/float), while for some a (visual styling), as li are placed beside of each other, while a inside of the li and technically can't be :not(:first-child) for example.
Using ul for such lists you should reset its styling with style-list: none; margin: 0; padding: 0.
You have a different id in JS and in HTML (attribute values in HTML and almost everything in JS are case-sensitive).
Check out the fixed version below.
/* Toggle between adding and removing the "responsive" class to
topnav when the user clicks on the icon */
function myFunction() {
var x = document.getElementById("myTopNav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
/* 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) {
.topnav ul li:not(:first-child) {
display: none;
}
.topnav ul li.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) {
.topnav.responsive {
position: relative;
}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive ul li {
float: none;
display: block;
text-align: left;
}
}
/* Hide the link that should open and close the topnav on small
screens */
.topnav .icon {
display: none;
}
/* BASIC STYLES */
/* Add a black background color to the top navigation */
.topnav {
background-color: #333;
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav ul {
list-style: none;
margin: 0;
padding: 0;
}
.topnav li {
float: left;
}
.topnav li a {
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
/* Change the color of links on hover */
.topnav li:hover {
background-color: #ddd;
color: black;
}
/* Add an active class to highlight the current page */
.active {
background-color: #4CAF50;
color: white;
}
/* Hide the link that should open and close the topnav on small screens */
.topnav .icon {
display: none;
}
<div id="header">
<div id="logo">
<img id="logo" src="your-choice-logo.jpg">
</div>
<nav class="topnav" id="myTopNav">
<ul>
<li><a class="active" href="#welcome-section">Home</a></li>
<li>Make Appointment</li>
<li>Contact Us</li>
<li>Services</li>
<li>Gallery</li>
<li>Reviews</li>
<li>Areas Served</li>
<li>Facebook</li>
<li class="icon">
<a href="javascript:void(0);" onclick="myFunction()">
<i class="fa fa-bars">=</i></a>
</li>
</ul>
</nav>
</div>
BTW, w3schools has nothing with W3 consortium. You should not consider w3schools as an authoritative resource. However it contains some simple and handy tutorials.

Categories