Close toggle menu after clicking outside of it and on a link - javascript

I'm currently using this simple toggle menu from w3school.
I was wondering how can this be edited in order to close when clicked outside of it or on a link (Logo, News, Contact, About)
<!DOCTYPE html>
<html>
<head>
<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">
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
.mobile-container {
max-width: 480px;
margin: auto;
background-color: #555;
height: 500px;
color: white;
border-radius: 10px;
}
.topnav {
overflow: hidden;
background-color: #333;
position: relative;
}
.topnav #myLinks {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #4CAF50;
color: white;
}
</style>
</head>
<body>
<!-- Simulate a smartphone / tablet -->
<div class="mobile-container">
<!-- Top Navigation Menu -->
<div class="topnav">
Logo
<div id="myLinks">
News
Contact
About
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<div style="padding-left:16px">
<h3>Vertical Mobile Navbar</h3>
<p>This example demonstrates how a navigation menu on a mobile/smart phone could look like.</p>
<p>Click on the hamburger menu (three bars) in the top right corner, to toggle the menu.</p>
</div>
<!-- End smartphone / tablet look -->
</div>
<script>
function myFunction() {
var x = document.getElementById("myLinks");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
</script>
</body>
</html>
JSFiddle Demo

The simplest way is to add an Event Listener in the whole document and use the conditional to see where you are clicking. Here's a Codepen with this logic: https://codepen.io/alac1984/pen/RwNVKOe
HTML:
<!DOCTYPE html>
<html>
<head>
<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">
</head>
<body>
<!-- Simulate a smartphone / tablet -->
<div class="mobile-container">
<!-- Top Navigation Menu -->
<div class="topnav">
Logo
<div id="myLinks">
News
Contact
About
</div>
<a href="#" class="icon" id="myButton">
<i id="itag" class="fa fa-bars"></i>
</a>
</div>
<div style="padding-left:16px">
<h3>Vertical Mobile Navbar</h3>
<p>This example demonstrates how a navigation menu on a mobile/smart phone could look like.</p>
<p>Click on the hamburger menu (three bars) in the top right corner, to toggle the menu.</p>
</div>
<!-- End smartphone / tablet look -->
</div>
CSS:
body {
font-family: Arial, Helvetica, sans-serif;
}
.mobile-container {
max-width: 480px;
margin: auto;
background-color: #555;
height: 500px;
color: white;
border-radius: 10px;
}
.topnav {
overflow: hidden;
background-color: #333;
position: relative;
}
.topnav #myLinks {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #4CAF50;
color: white;
}
JS:
const button = document.getElementById('myButton');
const div = document.getElementById('myLinks');
const icon = document.querySelector('.icon');
console.log(icon);
document.addEventListener('click', myFunction)
function myFunction(e) {
e.preventDefault();
console.log(e.target);
if((div.style.display === '' || div.style.display === 'none') && (e.target === button || e.target === itag)) {
div.style.display = 'block';
} else if((div.style.display === '' || div.style.display === 'none') && (e.target !== button || e.target !== itag)) {
div.style.display = 'none';
} else {
div.style.display = 'none';
}
}

Related

Make nav fill out full width without breaking the website

I wanted to know how I can make a nav menu I made fill out the whole page. A simple solution I thought of was to put it on absolute position and set top, left, bottom, right to 0. However, this caused it to go over the content and made the whole page a different color. Here's my HTML/CSS:
//JS
function myFunction() {
var x = document.getElementById("nav-links");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
/* CSS */
body {
font-family: 'Roboto', Arial, sans-serif;
background: white;
}
.topnav {
overflow: hidden;
background-color: #333;
position: relative;
width: 100%;
}
.topnav #nav-links {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #b47b5a;
color: white;
}
.body {
display: flex;
margin: auto;
min-height: 300vh;
}
<!--HTML-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="script/server.js"></script>
<title>Hello</title>
</head>
<body>
<header>
<div class="topnav">
Hello World!
<div id="nav-links">
Home
Contact
About
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
</header>
<div class="body">
<h1>Hello World!</h1>
</div>
<script src="script/script.js"></script>
</body>
</html>
I have tried every method I could think of and search of, but can't really pull it off.
If you try to make the topnav position to absolute, it is the correct way. You just must to adjust the padding or margin of the content below the topnav or set the padding top to the body so the topnav is not to go over the content.
//JS
function myFunction() {
var x = document.getElementById("nav-links");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
/* CSS */
body {
font-family: 'Roboto', Arial, sans-serif;
background: white;
padding-top: 50px;
}
.topnav {
overflow: hidden;
background-color: #333;
position: absolute;
z-index: 999;
top: 0;
left: 0;
right: 0;
width: 100%;
}
.topnav #nav-links {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #b47b5a;
color: white;
}
.body {
display: flex;
margin: auto;
min-height: 300vh;
}
<!--HTML-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="script/server.js"></script>
<title>Hello</title>
</head>
<body>
<header>
<div class="topnav">
Hello World!
<div id="nav-links">
Home
Contact
About
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
</header>
<div class="body">
<h1>Hello World!</h1>
</div>
<script src="script/script.js"></script>
</body>
</html>
Or you can make the topnav width to 100vw so the topnav will fully contain the width of your device, and set the body margin and padding to 0. But i not recomend to use this because sometimes it can make your website have horizontal scrolling, so the best way is still to use the first answer.
//JS
function myFunction() {
var x = document.getElementById("nav-links");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
/* CSS */
body {
font-family: 'Roboto', Arial, sans-serif;
background: white;
padding: 0;
margin: 0;
}
.topnav {
overflow: hidden;
background-color: #333;
position: relative;
width: 100vw;
}
.topnav #nav-links {
display: none;
}
.topnav a {
color: white;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
display: block;
}
.topnav a.icon {
background: black;
display: block;
position: absolute;
right: 0;
top: 0;
}
.topnav a:hover {
background-color: #ddd;
color: black;
}
.active {
background-color: #b47b5a;
color: white;
}
.body {
display: flex;
margin: auto;
min-height: 300vh;
}
<!--HTML-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="script/server.js"></script>
<title>Hello</title>
</head>
<body>
<header>
<div class="topnav">
Hello World!
<div id="nav-links">
Home
Contact
About
</div>
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
</header>
<div class="body">
<h1>Hello World!</h1>
</div>
<script src="script/script.js"></script>
</body>
</html>

Problem related to parent and child element

I am a newbie in Javascript coding. I wanted to do a mobile menu where if I click outside of the menu - the menu will disappear. I have done it successfully.
Now the problem is when I am clicking on the hamburger icon, the menu is not expanding. But when I am clicking on its parent element, it's working fine.
What's wrong in my Javascript code?
My code below
<!DOCTYPE html>
<html>
<head>
<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">
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #146875;
}
.topnav a {
float: left;
display: block;
color: #ffffFF; /*font color*/
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #00e5ff; /*top nav menu back hover color*/
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 900px) /* Mobile Screen Breakdown */
{
.topnav a:not(:nth-child(-n+3)) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
#media screen and (max-width: 900px) {
.topnav.responsive {position: relative;}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
</style>
</head>
<body>
<div class="topnav" id="myTopnav" >
Home
about Us
Address
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
var disappear = document.getElementById('myTopnav');
window.onclick = function(event) {
if (event.target.parentNode !== disappear){
disappear.className = "topnav";
}
}
</script>
</body>
</html>
The problem here is
if (event.target.parentNode !== disappear ){
disappear.className = "topnav";
}
when you are clicking on the icon( i tag) the parent node is the anchor tag. so its true. I have changed the code to below. And this should work for your example, also check the whole code snippet below
if (event.target.parentNode !== disappear && event.target.parentNode.parentNode !== disappear)
<!DOCTYPE html>
<html>
<head>
<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">
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #146875;
}
.topnav a {
float: left;
display: block;
color: #ffffFF; /*font color*/
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #00e5ff; /*top nav menu back hover color*/
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 900px) /* Mobile Screen Breakdown */
{
.topnav a:not(:nth-child(-n+3)) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
#media screen and (max-width: 900px) {
.topnav.responsive {position: relative;}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
</style>
</head>
<body>
<div class="topnav" id="myTopnav" >
Home
about Us
Address
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
var disappear = document.getElementById('myTopnav');
window.onclick = function(event) {
if (event.target.parentNode !== disappear && event.target.parentNode.parentNode !== disappear){
disappear.className = "topnav";
}
}
</script>
</body>
</html>

Dropdown menu is not working as expected in mobile view

I'm trying to add a dropdown menu to the mobile version of my site, but it doesn't seem to be working (I'm very new to web design).
The dropdown menu is correctly shown by clicking on the correspondent icon; the problem is that it is also shown by clicking at any point of the topnav menu. I just want the dropdown menu to appear only by clicking on the dropdown menu icon. Moreover, I'd the dropdown menu to disappear by clicking at any point outside of it. This is my code:
<!DOCTYPE html>
<html>
<head>
<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">
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #146875;
}
.topnav a {
float: left;
display: block;
color: #ffffFF; /*font color*/
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #00e5ff; /*top nav menu back hover color*/
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 900px) /* Mobile Screen Breakdown */
{
.topnav a:not(:nth-child(-n+3)) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
#media screen and (max-width: 900px) {
.topnav.responsive {position: relative;}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
</style>
</head>
<body>
<div class="topnav" id="myTopnav">
Home
Floor Plan
Address
Project Overview
Location Advantage
Download
Similar Projects
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<script>
let topnav = document.querySelector("#myTopnav");
topnav.onclick = function() {
this.classList.toggle('responsive');
}
</script>
</body>
</html>
Here you can try my code.
Hope you guys will help me.
You can check this answer. I have done the first part and another person helped me to do the second part.
Code below-
<!DOCTYPE html>
<html>
<head>
<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">
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
}
.topnav {
overflow: hidden;
background-color: #146875;
}
.topnav a {
float: left;
display: block;
color: #ffffFF; /*font color*/
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 17px;
}
.topnav a:hover {
background-color: #00e5ff; /*top nav menu back hover color*/
color: black;
}
.topnav .icon {
display: none;
}
#media screen and (max-width: 900px) /* Mobile Screen Breakdown */
{
.topnav a:not(:nth-child(-n+3)) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
}
#media screen and (max-width: 900px) {
.topnav.responsive {position: relative;}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
</style>
</head>
<body>
<div class="topnav" id="myTopnav" >
Home
about Us
Address
<a href="javascript:void(0);" class="icon" onclick="myFunction()">
<i class="fa fa-bars"></i>
</a>
</div>
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
var disappear = document.getElementById('myTopnav');
window.onclick = function(event) {
if (event.target.parentNode !== disappear && event.target.parentNode.parentNode !== disappear){
disappear.className = "topnav";
}
}
</script>
</body>
</html>

scroll tab to centre after being selected?

Ok, I've got a tab bar to scroll using touch swipe function and on a desktop to scroll and click
(for some reason when I add code into codepen the java code does not work, not sure why) it works when loaded on to my server
Sample attached: http://www.tcdesignstamford.co.uk
At the moment when you scroll/swipe to the next tab when the screen size is to small you cannot see which tab bar is being selected.
Is there a way to get the selected tab bar title at the top to centre so it does not go off screen??
[codepen code][2]
Hope you can help?
https://codepen.io/tim-cross-the-encoder/pen/wZLvmy
Thanks
Tim
Try to use the bootstrap library, and create a responsive navigation menu:
try to open this code snippet in responsive view, this will be collapsed:
and if you still want to use your own navigation menu, then you have to change design structure of HTML, there are a lot of errors, I just watched your HTML structure from URL link you provided.
if still want to your own navigation menu, let me know, I will create one!
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;
}
.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;
}
}
<!DOCTYPE html>
<html>
<head>
<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">
<style>
</style>
</head>
<body>
<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>
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
</script>
</body>
</html>

Responsive navigation menu in JavaScript

I am trying to build a responsive navigation menu for my website. However, it should also stick to the top when you scroll further down the page. This works fine on the normal 'desktop-size' menu, but when I expand the list items in the responsive navigation menu, the whole menu re-positions itself back to the top.
let navbar = document.querySelector("nav");
let offset = navbar.offsetTop;
// Makes the menu sticky
function stick() {
if (window.pageYOffset >= offset) {
navbar.classList.add("sticky")
} else {
navbar.classList.remove("sticky");
}
}
// Makes the menu responsive
function collapse() {
if (navbar.className === "responsive") {
navbar.classList.remove("responsive");
} else {
navbar.classList.add("responsive")
}
}
My JSFiddle: https://jsfiddle.net/MihkelPajunen/t37g6hsc/
Question: Is there a way to make the responsive navigation menu sticky, so that the menu is accessible at the top of the page, even when you scroll further down the page?
Remove the following rule:
nav.responsive {
position: relative;
}
As this is overriding the position: fixed rule.
Also, change the collapse function like so:
if (navbar.className.indexOf("responsive") >=0 ) {
As the class name will actually be something like "responsive sticky"
Here's a fork of that fiddle
Try To use this one instead of yours
<!DOCTYPE html>
<html>
<head>
<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">
<style>
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;
}
.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;
}
}
</style>
</head>
<body>
<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>
<script>
function myFunction() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav") {
x.className += " responsive";
} else {
x.className = "topnav";
}
}
</script>
</body>
</html>

Categories

Resources