I am stuck with a conflict for a "Sticky" and "Responsive" top menu.
When it is not scrolled and I click the BARS button to open the menu (in responsive state) it works ok. If I am scrolled down and the menu is "STICKY" it lost it "position:fixed" and goes all on top (back to position:relative).
Here is my codepen :
codepen for top navigation script conflict
// Function that expand the top menu when collapsed (responsive)
function opennav() {
var x = document.getElementById("myTopnav");
if (x.className === "topnav")
{x.className += " responsive";}
else
{x.className = "topnav";}}
// This is the function that stick the menu when scrolling
window.onscroll = function() {myFunction()};
var navbar = document.getElementById("myTopnav");
var sticky = navbar.offsetTop;
function myFunction() {
if
(window.pageYOffset >= sticky)
{navbar.classList.add("sticky");}
else
{navbar.classList.remove("sticky");}
}
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;
}
/* Responsive CSS for the top navigation menu */
#media screen and (max-width: 600px) {
.topnav a:not(:first-child) {
display: none;
}
.topnav a.icon {
float: right;
display: block;
}
.topnav.responsive {position: relative;}
.topnav.responsive .icon {
position: absolute;
right: 0;
top: 0;
}
.topnav.responsive a {
float: none;
display: block;
text-align: left;
}
}
/* Sticky CLASS that will be added when scrolling */
.sticky {
position: fixed;
top: 0;
width: 100%;
}
.sticky + .content {
padding-top: 60px;
}
<body>
<div class="topnav" id="myTopnav">
Home
News
Contact
About
<a href="javascript:void(0);" class="icon" onclick="opennav()">
<i class="fa fa-bars"></i>
</a>
</div>
<div style="padding-left:16px">
<!-- Put large text in this <p> to scroll -->
<p>LOREM IPSUM</p>
</div>
</body>
First, don't use float. We are not leaving in 1995. Go with flexbox or grid.
Second, your code is all over the place. Multiple script tags in HTML section, the multiple usages of the same media query... It's difficult to read your code.
Third, what you want to do can be done just by using CSS. You only need JS to open submenu. To do that just add a class.
I suggest you watch a Youtube video about the responsive menu.
Related
I am facing a problem with my top navigation menu. On small screens my menu is opened by clicking the hamburger icon. However, I want the menu to collapse after clicking on one of the items. I hope you guys love to help this newbie. Thank you.
/* 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";
}
}
/* Add a black background color to the top navigation */
.topnav {
background-color: #333;
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: #4CAF50;
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;
}
}
<!-- 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">
<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>
</div>
When Im running this code works fine but not disappearing the dropdown. Hope you guys help me.
Add to each one of your anchor tags
onclick="myFunction()"
To toggle classes on an element use
element.classList.toggle()
Use meaningful variable names like myTopNav instead of x.
No changes to your CSS.
MDN classList
function myFunction() {
var myTopNav = document.getElementById("myTopnav");
myTopNav.classList.toggle("responsive");
}
/* Add a black background color to the top navigation */
.topnav {
background-color: #333;
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: #4CAF50;
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;
}
}
<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>
I'm fairly new to css and website design in general. I have created a site with a navbar, that scrolls down with the page, so it always stays on top:
<div class="topnav" id="navbar">
Startseite
Übersicht
...
This does work, I have a Sticky-Class in my css, as well as some design options:
.topnav {
overflow: hidden;
background-color: #333;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
}
and this js which assigns it to my navbar, when it's scrolling so far up, that it would disappear.
window.onscroll = function() {myFunction()};
var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
navbar.classList.add("sticky")
} else {
navbar.classList.remove("sticky");
}
}
As you can see on the picture, from the moment on that the navbar is in a "scrolled" state, it expands a little bit to the right, so that it hits the side of the page.
This is a behaviour which I find very confusing, can anyone explain to me why this happenes, and how I can get it to just keep its size with the space to the side of the page? I figured it could have to do something with the expand 100%, but why is it then not bumping into the left side of the page as well?
This happens when you scroll because the div is not properly bound to the viewport.
// When the user scrolls the page, execute myFunction
window.onscroll = function() {
myFunction()
};
var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
navbar.classList.add("sticky")
} else {
navbar.classList.remove("sticky");
}
}
* {
box-sizing: border-box;
margin: 0;
}
body {
font-family: Arial;
max-width: 92vw;
position: relative;
background: #f1f1f1;
margin-right: auto;
margin-left: auto;
}
.topnav {
overflow: hidden;
background-color: #333;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
/* The sticky class is added to the navbar with JS when it reaches its scroll position*/
.sticky {
position: fixed;
top: 0;
right: 0;
left: 0;
margin-right: auto;
margin-left: auto;
max-width: 92vw;
}
<div class="topnav" id="navbar">
Startseite
Übersicht
Über uns
<a style="float:right">
<form action="/search">
<label for="player_seach">Suche:
<input id="player_seach" name="player_search">
</label>
</form>
</a>
<a href="/profile" style="float:right">
</a>
</div>
<div style="min-height: 500px; width: 100%">
</div>
You can add media queries to help declutter the navbar upon resizing.
Happy learning!
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>
So basically I have a nav bar that floats left. The page is responsive so that when the screen is below a certain size, the nav bar disappears (except the Home link) and a hamburger drop-down menu pops up on the right. What I'm trying to do is figure out how to make the navigation bar centered and have it completely disappear when the screen size is reduced and have the hamburger icon appear and become centered on the screen.
HTML:
<div class="topnav" id="myTopnav">
<nav>
Home
History
Information
Gallery
Videos
Exercises
Contact
Links
☰
</nav>
</div>
CSS:
/* Add a black background color to the top navigation */
.topnav {
background-color: #000000;
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
display: block;
color: #FFFFFF;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 2.25em;
margin-bottom: 1.25%;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #2C3539;
color: #FFFFFF;
}
/* 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;
}
/* 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;
}
}
Javascript:
<script>
/* 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";
}
}
</script>
Any help in doing this would be appreciated!
Removing floats and display: block, and using inline-block may fix your problems
display: inline-block;
Your new code:
/* Add a black background color to the top navigation */
.topnav {
background-color: #000000;
overflow: hidden;
}
/* Style the links inside the navigation bar */
.topnav a {
display: inline-block;
color: #FFFFFF;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 2.25em;
margin-bottom: 1.25%;
}
/* Change the color of links on hover */
.topnav a:hover {
background-color: #2C3539;
color: #FFFFFF;
}
:D
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.