Creating a vertical responsive navigation bar using javascript - javascript

I'm currently trying to create a website from scratch, seen as I have the time to practice.
So far, I have got a working navigation bar (one which does not actually take you to other pages yet but does actually work ).
I decided to make this navigation bar responsive, as it is quite a big bar.
I have given the option of a vertical bar at a click of a button.
To note, the button is only available to the user when the browser is less than 900px width.
My current issue is that when the button is pressed, nothing is being displayed. I have ensured the javascript for the button is working, via trial and error but still have no luck.
I am new to this, so forgive me if my error is silly but any help would be greatly appreciated.
To help give an idea of what I am trying to achieve, here is the link I have been using as guidance: https://www.w3schools.com/howto/howto_js_topnav_responsive.asp
If the issue lays within the fact that I am using an 'unordered list' tag to align my navigation bar to the right and my logo to the left, then any alternative way is welcome too!
Thank you.
P.s. ignore the names of each section in the navigation, I was just filling in the spaces for now ^^
body{
background-color: grey;
margin:0;
}
/*----------------------NAVIGATION BAR----------------------*/
.nav-container{
background-color: white;
float: right;
height: 80px;
position: absolute;
width: 100%;
margin-top: 0;
}
#nav-menu{
float:right;
padding: 13px 13px;
}
#nav-menu li{
display:inline-block;
font-size: 20px;
padding: 10px 12px;
text-align: center;
}
#nav-menu li a:not(.nav-active){
color: black;
text-decoration: none;
}
#nav-menu li a:hover:not(#logo){
color: #0aaaa0;
}
.nav-active {
color: #0aaaa0;
text-decoration: none;
}
/* LOGO */
#logo{
padding: 0px 13px;
float: left;
font-size: 27px;
}
/* Hide the link that should open and close the topnav on small screens */
#nav-menu .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: 900px) {
#nav-menu li a:not(.icon) {display: none;}
#nav-menu li 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: 900px) {
.nav-bar.responsive {position: relative;}
.nav-bar.responsive li a.icon{
position: relative;
right: 0;
top: 0;
}
.nav-bar.responsive li a{
float: none;
display: block;
text-align: left;
position: relative;
}
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link rel="stylesheet" href="practice.css">
<!-- 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>
<!-- NAVIGATION BAR -->
<div class="nav-container">
<ul id="logo">Dellion</ul>
<ul class="nav-bar" id="nav-menu">
<li><a class="nav-active" href="index.html">Home</a></li>
<li>Cars</li>
<li>Charities</li>
<li>Pros</li>
<li>Games</li>
<li>Auctions</li>
<li>Support</li>
<li><a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i></a></li>
</ul>
</div>
<script>
function myFunction() {
var x = document.getElementById("nav-menu");
if (x.className === "nav-bar") {
x.className += " responsive";
} else {
x.className = "nav-bar";
}
}
</script>
</body>
</html>

Simplify your layout by using flexbox
function myFunction() {
var x = document.getElementById("nav-menu");
if (x.className === "nav-bar") {
x.className += " responsive";
} else {
x.className = "nav-bar";
}
}
body {
background-color: grey;
margin: 0;
}
.nav-container {
display: flex;
background-color: white;
min-height: 80px;
width: 100%;
align-items: center;
flex-wrap: wrap;
}
#logo {
font-size: 27px;
padding: 0 13px;
height: 80px;
line-height: 80px;
}
.nav-bar {
flex-direction: row;
}
.nav-bar li {
list-style: none;
}
.nav-bar a {
color: #000;
font-size: 20px;
padding: 10px 12px;
text-decoration: none;
}
.nav-links {
margin-left: auto;
padding-right: 20px;
display: flex;
flex: 1;
justify-content: flex-end;
}
.hamburger .icon {
/* remove the styling, this code is for illustration purpose only*/
height: 40px;
width: 40px;
background: grey;
border: 1px solid #000;
}
.nav-bar,
.hamburger .icon {
display: none;
}
.hamburger {
position: absolute;
right: 20px;
top: 20px;
}
#media screen and (min-width: 901px) {
.nav-bar,
.nav-bar.responsive {
display: flex;
align-items: center;
}
}
#media screen and (max-width: 900px) {
.hamburger .icon {
display: block
}
.nav-bar.responsive {
display: flex;
flex-direction: column;
width: 100%;
margin: 0;
padding: 0;
}
.nav-links {
flex-basis: 100%;
margin: 0;
padding: 0;
}
.nav-bar li {
padding: 10px 0;
}
}
<div class="nav-container">
<div id="logo">Dellion</div>
<div class="nav-links">
<ul class="nav-bar" id="nav-menu">
<li><a class="nav-active" href="index.html">Home</a></li>
<li>Cars</li>
<li>Charities</li>
<li>Pros</li>
<li>Games</li>
<li>Auctions</li>
<li>Support</li>
</ul>
<div class="hamburger">
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i></a>
</div>
</div>
</div>

There is a very simple way:
.nav-container{
background-color: white;
/* float: right; */
height: 80px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
margin-top: 0;
}
#nav-menu{
/* float:right; */
/* padding: 13px 13px; */
}
#nav-menu li{
display:inline-block;
font-size: 20px;
padding: 10px 12px;
text-align: center;
}
#nav-menu li a:not(.nav-active){
color: black;
text-decoration: none;
}
#nav-menu li a:hover:not(#logo){
color: #0aaaa0;
}
.nav-active {
color: #0aaaa0;
text-decoration: none;
}
/* LOGO */
#logo{
padding: 0px 13px;
/* float: left; */
font-size: 27px;
}
/* Hide the link that should open and close the topnav on small screens */
#nav-menu .icon {
display: none;
}
And I recommended you to read this useful article about css Flexbox.

I think part of your problem is, :
Javascript:
if (x.className === "nav-bar") {
x.className += " responsive"; //add space after quotation mark, otherwise class is added adjacent
} else {
x.className = "nav-bar";
}
Css:
.nav-bar.responsive li a{
float: none;
display: block !important; /* I think this needs to be crushed with important */
text-align: left;
/* position: relative; you don't need it */
}

you can simply do it with css
flex-direction: column;

Related

How can I turn my navbar into Hamburger menu for mobile using responsive design?

How could I turn this navbar I made using CSS into Hamburger menu for mobile ? It needs to be responsive. I first tried using bootstrap but I'd like it to use CSS
Here's my codepen : https://codepen.io/Softee/pen/WNZpXGa
Thanks in advance for your help!
Here's the code :
header {
background: #583760;
}
header::after {
content: '';
display: table;
clear: both;
}
.logo {
max-height: 90px;
margin-left: 60px;
float: left;
padding: 10px;
}
nav {
margin-right: 60px;
float: right;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
margin-left: 40px;
padding-top: 50px;
}
nav a {
color: white;
font-weight: bold;
text-decoration: none;
text-transform: uppercase;
}
nav a:hover {
color: black;
}
#nav:not(:target) {
right: -100%;
transition: right 1.5s;
}
#nav:target {
right: 0;
transition: right 1s;
}
<header>
<div class="container">
<img src="images/GameStar-Blanc.png" alt="logo" class="logo">
<nav>
<ul>
<li>A LA UNE </li>
<li>L'ACTUALITE</li>
<li>GUIDES ET ASTUCES</li>
<li>PROCHAINEMENT</li>
</ul>
</nav>
</header>
First of all, you will have to refactor the global CSS by using flex and grid which are the standard for responsive design. It is way more simple and powerful than using floats and other ancient stuff:
<header class="header">
<img src="..." />
<nav> ... </nav>
</header>
.header {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
padding: 20px 60px;
}
With justify-content: space-between you tell the container that the elements inside of it (.logo and nav) will be spaced, the first (logo) at the left and the second (nav) at the right, no need to use float. The property works only if you set display: flex. With align-items: center; you tell the flex container how you want to vertically align your items.
Then, you can assign a class to ul and populate it as follows:
.list {
display: grid;
grid-auto-flow: column;
list-style-type: none;
column-gap: 20px;
padding: 0;
}
Here you're telling to <ul> element that all the <li> elements inside of it, should compose a grid of n columns as many <li> elements and that you want 20px of space between each of them. The property column-gap works only if you set display: grid. The padding should always be 0 or the browser will add some padding by default. You don't want it so you specify 0.
Now, you can use a powerful combo to set the width of the list items by creating a class and assigning it to your <li> elements:
.listItem {
width: min-content;
white-space: nowrap;
}
Here you're just telling to the list items that their width should be automatic, based on the words length. With white-space: nowrap you're telling to the list items that you never want the text to start a new line after a space. For example, "GUIDES ET ASTUCES" will always be placed on a single line. At the same time you're also setting the width for each column of the grid created before.
Now, create a button and wrap it together with the logo in a new div:
<div class="mobileHeader">
<img src="images/GameStar-Blanc.png" alt="logo" class="logo">
<button class="hamburger">Menu</button>
</div>
Basically, this will be your mobile header with the logo on the left and the button on the right. The menu will be placed below.
Create a global CSS rule and tell the button you never want to display it:
.hamburger {
display: none;
}
Now for the mobile menu, you should change the appearance of the <nav> container and all its child element that you want to change. From now on your code should be wrapped around a media query, place the media queries at the bottom of your CSS file or at least, below the rules defined before:
#media screen and (max-width: 800px) {
// CSS code
}
Create another CSS rule targeting all the devices with a max resolution of 800px:
#media screen and (max-width: 800px) {
.hamburger {
display: block;
}
}
In short, you just said: "The menu button should always be hidden, but when a device has a width from 0 to 800px, I want to display it.
Now create another rule inside the media query #media screen and (max-width: 800px) and do the same you did for the header:
.mobileHeader {
width: 100%;
display: flex;
justify-content: space-between;
}
Basically you want that a certain width, the header is something like:
Now you should have two elements inside your <header>, <div> and <nav>, let's create a rule and tell the header that you would like to display those elements one below the other:
.header {
flex-direction: column;
padding: 20px;
}
Basically it is just like grid-auto-flow: row for grids.
Now do the same for the list, this time you want the opposite, you want that all the items will compose a grid with n rows and just one column:
.list {
grid-auto-flow: row;
list-style-type: none;
row-gap: 40px;
column-gap: 0;
justify-items: center;
}
With justify-items: center you're instructing the list to center the list items. It works only with display: grid, since you set display: grid in a global rule, you don't need to write it again as long as you don't need to change it.
Now assign a class to your <nav> and enter another rule in the media query:
.menu {
display: none;
}
Since your menu should be hidden when an user visits the website on mobile, it should be set on display: none by default.
Now, set a rule to target only devices with a width of 801 px and more with (min-width: 801px):
#media screen and (min-width: 801px) {
.menu {
display: block !important;
}
}
No matter what, you always want the menu to be displayed for devices which have a resolution wider than 800px.
Now, if you shrink your window the mobile menu should be vanished and here you need a bit of JS to open and close it, I am not going into the details since your question is totally related to CSS and I will only confuse you by going deeper but you will find everything in the pen I made for you.
https://codepen.io/alienopolis/pen/NWapXWZ
Finally, I would recommend you to take this free tutorial which covers everything you need to know about responsive design with CSS:
https://www.freecodecamp.org/news/css-flexbox-and-grid-tutorial/
HTML
<header class="header">
<div class="mobileHeader">
<img src="images/GameStar-Blanc.png" alt="logo" class="logo">
<button onclick={openMenu()} class="hamburger">Menu</button>
</div>
<nav class="menu">
<ul class="list">
<li class="listItem">A LA UNE </li>
<li>L'ACTUALITE</li>
<li>GUIDES ET ASTUCES</li>
<li>PROCHAINEMENT</li>
</ul>
</nav>
</header>
CSS
body {
width: 90%;
height: 800px;
}
.header {
display: flex;
width: 100%;
justify-content: space-between;
background: #583760;
align-items: center;
padding: 20px 60px;
}
.logo {
color: white;
}
.list {
display: grid;
grid-auto-flow: column;
list-style-type: none;
column-gap: 40px;
}
.listItem {
width: min-content;
white-space: nowrap;
}
nav a {
color: white;
font-weight: bold;
text-decoration: none;
text-transform: uppercase;
}
nav a:hover {
color: black;
}
.hamburger {
display: none;
}
#media screen and (min-width: 801px) {
.menu {
display: block !important;
}
}
#media screen and (max-width: 800px) {
.header {
flex-direction: column;
padding: 20px;
}
.mobileHeader {
width: 100%;
display: flex;
justify-content: space-between;
}
.hamburger {
display: block;
}
.menu {
display: none;
}
.list {
grid-auto-flow: row;
list-style-type: none;
row-gap: 40px;
column-gap: 0;
justify-items: center;
}
}
JS
const menu = document.querySelector(".menu");
let open;
function openMenu() {
if (open) {
menu.style.display = "none";
open = false;
} else if (!open) {
menu.style.display = "block";
open = true;
}
}
Responsive means you'll use media queries.
If your current CSS represents the way you want the menu to look on the desktop, then you wrap that menu-related css within a media query, which matches whatever your definition of desktop is.
something like:
/* not-menu-related generic css here ... */
/* menu-related css that should be used on both desktop/mobile here ... */
#media screen and (min-width:240px) and (max-width:480px) {
/* all your current (desktop) menu-related css here */
}
After that, you can make a similar #media .... { ... } block for mobile, and add the relevant CSS in there that makes it look whatever way you prefer there.
threw this together using #media and display:block, display:none hope it helps
header {
background: #583760;
}
header::after {
content: '';
display: table;
clear: both;
}
.logo {
max-height: 90px;
margin-left: 60px;
float: left;
padding: 10px;
}
nav {
margin-right: 60px;
float: right;
}
nav ul {
margin: 0;
padding: 0;
list-style: none;
}
nav li {
display: inline-block;
margin-left: 40px;
padding-top: 50px;
}
nav a {
color: white;
font-weight: bold;
text-decoration: none;
text-transform: uppercase;
}
nav a:hover {
color: black;
}
#nav:not(:target) {
right: -100%;
transition: right 1.5s;
}
#nav:target {
right: 0;
transition: right 1s;
}
.hamburgerIcon {
display: none;
}
#media only screen and (max-width: 600px) {
.hamburgerIcon {
display: block;
}
.hamburgerIcon div {
width: 35px;
height: 5px;
background-color: black;
margin: 6px 0;
}
nav a {
display: none;
}
}
<header>
<div class="container">
<img src="https://via.placeholder.com/60" alt="logo" class="logo">
<nav>
<ul>
<li>A LA UNE </li>
<li>L'ACTUALITE</li>
<li>GUIDES ET ASTUCES</li>
<li>PROCHAINEMENT</li>
<li>
<div class='hamburgerIcon'>
<div></div>
<div></div>
<div '></div>
</div>
</ul>
</nav>
</header>
also see w3schools.com/howto/howto_js_mobile_navbar.asp for further help building the nav if you need
Here's a solution with minimal JS.
You'll want to adjust your CSS for smaller screen sizes and use a media query for your larger screen sizes styles like, #media only screen and (min-width: 768px).
Then you'll want to add a click event to your nav to toggle an "open" class and style accordingly:
document.getElementById('navigation').onclick = () => {
document.body.classList.toggle('nav-open')
}
:root {
--header-height: 100px;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
header {
position: relative;
background: #583760;
height: var( --header-height);
}
header::after {
content: '';
display: table;
clear: both;
}
.container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
height: 100%;
}
.container img {
height: 100%;
}
.hamburger {
color: white;
font-size: 36px;
user-select: none;
}
nav {
cursor: pointer;
}
nav a {
color: white;
font-weight: bold;
text-decoration: none;
text-transform: uppercase;
}
nav ul {
position: fixed;
top: 100px;
right: 0;
height: 100%;
width: 100%;
text-align: center;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 30px;
margin: 0;
list-style: none;
background: #583760;
display: none;
}
nav ul li {
padding: 10px 0;
}
.nav-open nav ul {
display: flex;
}
#media only screen and (min-width: 768px) {
.logo {
max-height: 90px;
margin-left: 60px;
float: left;
padding: 10px;
}
.hamburger {
display: none;
}
nav {
margin-right: 60px;
float: right;
}
nav ul {
display: block;
padding: 0;
position: relative;
top: unset;
right: unset;
height: unset;
}
nav li {
display: inline-block;
margin-left: 40px;
}
nav a:hover {
color: black;
}
#nav:not(:target) {
right: -100%;
transition: right 1.5s;
}
#nav:target {
right: 0;
transition: right 1s;
}
}
<header>
<div class="container">
<img src="https://via.placeholder.com/150" alt="logo" class="logo">
<nav id="navigation">
<div class="hamburger">≡</div>
<ul id="navigationItems">
<li>A LA UNE </li>
<li>L'ACTUALITE</li>
<li>GUIDES ET ASTUCES</li>
<li>PROCHAINEMENT</li>
</ul>
</nav>
</header>

Can't make reappear hidden divs in a navbar once a button is pressed with help of media queries

I'm trying to reproduce this responsive Navbar offered by W3 schools.
So far everything works except that I don't get the other divs (which function as navigation option) to reappear as a vertical list.
I tried changing to background color of the first div (which should always appear no matter what) upon button press and it does work, meaning that the onClick of the navigation div does work. What I don't get is why won't the other divs show up?
Here is the relevant HTML code
<div id=navbar class="respNavBar">
<div id="first">
<a><b>TEST</b></a>
</div>
<div class="extra">
<a><b>TEST</b></a>
</div>
<div class="extra">
<a><b>TEST</b></a>
</div>
<div class="extra">
<a><b>TEST</b></a>
</div>
<div class=navigation href="javascript:void(0);" onclick="showRespBar()">
<a><b>...</b></a>
</div>
CSS CODE
.greetingsText {
font-family: Raleway;
font-size: 50px;
}
.greetings {
box-shadow: 3px 6px #232323;
margin-right: 67%;
min-width: 165px;
}
#navbar {
height: 55px;
background-color: #393939;
box-shadow: 3px 6px #232323;
display: flex;
flex-direction: row;
justify-content: space-evenly;
align-items: center; /* this makes shit center align vertically*/
min-width: 375px;
}
#navbar div:hover {
background-color: #a4a4a4;
}
.navigation {
display: none;
}
#navbar div {
height: 100%;
}
a {
margin-top: 10px;
display: block;
font-family: Raleway;
font-size: 30px;
text-align: center; /*this makes shit center horizaontally*/
}
.container {
margin-left: 12%;
margin-top: 2%;
margin-right: 12%;
}
#media screen and (max-width: 750px) {
#navbar {
display: block;
}
#navbar div:not(#first):not(.navigation) {display: none;}
#first {
float: left;
display: block;
}
.navigation {
display: block;
float: right;
}
}
#media screen and (max-width: 750px){
.extra {
float: none;
display: block;
text-align: left;
}
}
JS CODE
function showRespBar() {
var className = document.getElementById("navbar").className;
if (className === "respNavBar") {
document.getElementById("navbar").className += "additional";
} else {
document.getElementById("navbar").className = "respNavBar";
}
alert(className);
}
One possible issue i found in your JS code, inside if condition,
document.getElementById("navbar").className += "additional"; should be document.getElementById("navbar").className += " additional";
You are missing a space, due to which respNavBaradditional class gets applied to navbar instead of respNavBar addition.

Make media query take priority over function

I am trying to make my navigation bar responsive but I am having issues making an image (our logo) appear and disappear when desired.
First of all the default is that the navigation bar has our standard logo displayed and the alternative one hidden:
Then when moving onto a smaller screen I am using a media query to change the color of the navigation bar, hide one logo, show another logo and add a hamburger menu.
Since I found that clicking the hamburger menu, and viewing the links in block display, the alternative logo sat in the way of the first link. So I used a function to hide it (triggered upon clicking on the hamburger menu)
So far so good, clicking on the hamburger menu toggles the logo appearing and disappearing. However, if you collapse the menu without going to another page the function toggles the logo on again - which is fine until you resize the page and make it larger. Then the logo just sits in the way and isn't made to disappear by the media query.
I have tried using !important tags but honestly at a bit of a loss of how to do this final step. Any feedback would be much appreciated!
HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="../Style/Basic Styling.css"/>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="page">
<div id="page_container">
<!--Nav Bar Start -->
<div class="topnav" id="myTopnav">
<img id="CElogo" src="https://imgur.com/gallery/Zmuzg62" alt="CE logo" title="CE logo" >
<img id="CElogoNoTextID" class="CElogoNoText" src="https://i.imgur.com/Kr3ACDH.jpg" alt="CE logo No Text" title="CE logo No Text" >
Blog
Pricing
<a id="homeNav" class="homeNavClass" href="http://localhost:63342/untitled/Home Page/Climate Edge.html">Home</a>
☰
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
var y = document.getElementById("CElogoNoTextID");
if (y.style.display === "none" ) {
y.style.display = "block";
} else {
y.style.display = "none";
}
}
</script>
</div>
</div>
</div>
</body>
</html>
CSS
body {
margin:0;
}
#page {
margin:0;
background:none;
overflow:auto;
}
#page_container {
margin:0 0px;
}
#HeaderImage {
width: 100%;
line-height:1px;
z-index: 3;
}
.topnav {
overflow: hidden;
width: 100%;
margin-top: 0%;
z-index: 2;
position: absolute;
background: none;
}
#homeNav{
display:none; !important
}
.topnav a {
float: right;
color: black;
padding: 25px 16px;
text-decoration: none;
z-index: 1;
font-family: Lato;
font-size: 24px;
font-style: normal;
font-variant: normal;
font-weight: 500;
line-height: 26.4px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav img {
width: 130px;
margin-left: 5px;
margin-top: 7px;
position:absolute;
overflow: auto;
}
#CElogoNoTextID {
display: none;
}
.topnav .icon {
display: none;
}
#DataToAction {
width: 30vw;
margin-left: 35vw;
margin-right: 35vw;
margin-top: 5vw;
position:absolute;
}
#media screen and (min-width: 601px)and (max-width: 1000px) {
.topnav a {
font-size: 16px;
}
#DataToAction{
display:none;
}
.topnav img {
display:none;
}
#CElogoNoTextID{
display: none; !important;
}
}
#media screen and (max-width: 600px) {
#HeaderImage {
margin-top: 80px;
}
#CElogoNoTextID{
display:block;
float:left;
margin-top: 0px;
width: 90px;
}
.topnav {
background: #29ABE2;
}
.topnav a {display: none;}
.topnav a.icon {
float: right;
display: block;
}
#homeNav{
float: right;
display: block;
color: white;
}
.topnav img{
display: none;
}
#DataToAction{
display:none;
}
}
#media screen and (max-width: 600px) {
.topnav.responsive {position: relative;}
.topnav.responsive a.icon {
position: absolute;
right: 0;
top: 0;
color:black;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
.topnav.responsive a.homeNavClass {
display: block;
text-align: left; !important;
}
}
Please see the jsfiddle here

slide out nav not working

function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
body {margin:0;}
ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #333;
}
li {
float: left;
}
.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 .icon {
display: none;
}
#media screen and (max-width: 600px) {
.topnav li: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;
}
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<ul class="topnav" id="myTopnav">
<li>Home</li>
<li>News</li>
<li>Contact</li>
<li>About</li>
<li>☰</li>
</ul>
<div style="padding-left:16px">
<h2>Responsive Topnav Example</h2>
<p>Resize the browser window to see how it works.</p>
</div>
</body>
</html>
In the code when the screen size is less than 600px the home tab stays and the rest should be available through the hamburger icon which should show up at the right corner but it doesn't work.
What did I do wrong?
What changes should I do to make it work?
Please Help
Though other answers provide a solution using your current code, I would recommend a different approach for quite a few things...
Unobtrusive JS is important for a better SoC (Separation of Concerns). Keep it out of the HTML/global scope with the addEventListener() method and, optionally, an IIFE.
CSS should take more of a mobile-first approach.
:hover should nearly always be accompanied by :focus. Use the tab key to jump from control to control and you'll see why. Not everyone is using a mouse.
HTML should probably be taking advantage of HTML5 semantics
This is less important, but I would still show the "Home" link.
Update: Also, use the proper heading level (h2 is not the top level)
(function() {
'use strict';
var headerEl = document.querySelector('body > header');
var btnEl = document.querySelector('.menu-btn');
if(btnEl && headerEl) {
btnEl.addEventListener('click', function() {
headerEl.classList.toggle('open');
});
}
})();
.page-header {
background-color: #333;
color: #f2f2f2;
overflow: hidden;
}
.page-header a { display: block; }
.page-header a,
.menu-btn {
color: inherit;
text-decoration: none;
font-size: 17px;
padding: 14px 16px;
}
button.menu-btn {
border: none;
background: none;
cursor: pointer;
}
.page-header a:hover,
.page-header a:focus,
.menu-btn:hover,
.menu-btn:focus {
background-color: #ddd;
color: black;
outline: none;
}
.page-header:not(.open) a { display:none; }
.menu-btn { float: right; }
#media(min-width: 768px) {
.page-header.page-header a { display: inline-block; }
.menu-btn { display: none; }
}
<header class="page-header">
<button class="menu-btn">☰</button>
<nav>
Home
Contact
About
</nav>
</header>
<main>
<h1>Responsive Topnav Example</h1>
<p>Resize the browser window to see how it works.</p>
</main>
The main issue is that you are hiding the elements when you go to the small state, but not showing them when you add the .responsive class. I have made some updates for you here:
https://jsfiddle.net/9xxzsypu/
.topnav.responsive li.item:not(:first-child) { display: block!important; }
Try this in your first media query:
#media screen and (max-width: 600px) {
.topnav li:not(:first-child):not(:last-child) {
display: none;
}
}
You basically set every list item in .topnav to display: none except for the first one. This made the hamburger menu invisible too.

How to make the menubar work like a proper menubar without bootstrap?

How do you a menubar work properly menubar with the functions:
*Clicking on hamburger-icon will display the nav-links.
*Clicking on nav-links will hide the menubar.
(without using bootstrap, but doing it from scratch)
I understand that many have asked this question. I have looked at many different solutions, with JS and Jquery, and I have encountered several problems because I really dont understand JS or Jquery fully.
This is how far I´ve gotten. Go to my website hung.no so you can see the problem. On my website, you should minimize the window to get to the hamburger bar. Then you should click on that bar. After that click on one of the nav-links. It closes, but when you try to click on the hamburger bar again, it does not work.
//Navbar collapses to menubar
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
//Jquery code ON MY WEBSITE. I cannot display it here.
//This is the source
//<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
//$(document).ready(function(){
// $(".nav-link").click(function(){
// $(".nav-toggle").hide();
// });
//});
//$(document).ready(function(){
// $(".nav-show").click(function(){
// $(".nav-toggle").show();
// });
//});
/*mobile navbar*/
.topnav .icon {
display: none;
}
.topnav {
overflow: hidden;
background-color: #fff;
width: 100%;
position: fixed;
z-index: 1000;
}
.topnav a {
float: right;
display: block;
color: #000;
padding: 10px 10px;
text-decoration: none;
font-size: 12px;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 700px) {
.topnav a:not(:first-child) {display: none;}
.topnav a.icon {
float: right;
display: block;
}
#myNavbar{
display: none;
}
}
#media screen and (max-width: 700px) {
.topnav.responsive {
position: fixed;
width: 100%;
top: 0;
}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none!important;
display: block;
text-align: left;
}
.mob-font-size{
font-size: 22px;
width: 100%;
}
.mob-logo-size{
width: 177px;
height: 260px;
}
}
/*dekstop navbar*/
#myNavbar{
position: fixed;
width: 100%;
background: white;
border-style: solid;
border-width: 0 0 1px 0;
border-color: #E8E8E8;
z-index: 9999;
}
.float-right-nav{
padding: 8px 15px;
float: right;
}
#myNavbar ul {
list-style-type: none;
margin: 0;
padding: 0;
overflow: hidden;
}
li a {
display: block;
color: #000;
text-align: center;
text-decoration: none;
}
div.container
{
margin: 0 auto;
padding: 6px 3em;
text-align: center;
}
div.container a
{
color: #000;
text-decoration: none;
font: 12px Raleway-medium;
margin: 0px 20px;
padding: 5px 5px;
position: relative;
z-index: 1;
cursor: pointer;
}
<!--desktop navbar-->
<div id="myNavbar">
<div class="container">
<ul>
<li style="float:left"><img src="svg/navlogo.svg" alt=""></li>
<li class="float-right-nav"><span class="medium">KONTAKT</span></li>
<li class="float-right-nav"><span class="medium">PRIS</span></li>
<li class="float-right-nav"><span class="medium">GARANTIER</span></li>
<li class="float-right-nav"><span class="medium">OM MEG</span></li>
</ul>
</div>
</div>
<!--Mobile navbar the classes nav-link and nav-toggle is used in the Jquery code located in the Javascript-section in this Code Snippet-->
<div class="topnav" id="myTopnav">
<a style="float:left" href="#home"><img src="svg/navlogo.svg" alt="" height="20" width="18"></a>
<a class="nav-link nav-toggle"href="#Kontakt"><span class="medium">KONTAKT</span></a>
<a class="nav-link nav-toggle"href="#Pris"><span class="medium">PRIS</span></a>
<a class="nav-link nav-toggle"href="#Garantier"><span class="medium">GARANTIER</span></a>
<a class="nav-link nav-toggle"href="#Ommeg"><span class="medium">OM MEG</span></a>
☰
</div>
I see a problem in your javascript function "myFunction"
When you click a first time, you append class "resposive", but when you click again the flow moves to "else" and then it remove "responsive" so you are removing that behaviour.
If you remove that flow then the nav works fine.

Categories

Resources