I need help. I have a nav bar with buttons. I want them to change color when clicked on and when the scroll bar hits the right anchor (it is a one page website). But the script is not working, only the first button gets white at the beginning but when scrolling....nothing happen. Please Help, I m a dumb truck :-)
// Cache selectors
var lastId,
topMenu = $("#nav"),
topMenuHeight = topMenu.outerHeight() + 15,
// All list items
menuItems = topMenu.find("a"),
// Anchors corresponding to menu items
scrollItems = menuItems.map(function() {
var item = $($(this).attr("href"));
if (item.length) {
return item;
}
});
// Bind click handler to menu items
// so we can get a fancy scroll animation
menuItems.click(function(e) {
var href = $(this).attr("href"),
offsetTop = href === "#" ? 0 : $(href).offset().top - topMenuHeight + 1;
$('html, body').stop().animate({
scrollTop: offsetTop
}, 300);
e.preventDefault();
});
// Bind to scroll
$(window).scroll(function() {
// Get container scroll position
var fromTop = $(this).scrollTop() + topMenuHeight;
// Get id of current scroll item
var cur = scrollItems.map(function() {
if ($(this).offset().top < fromTop)
return this;
});
// Get the id of the current element
cur = cur[cur.length - 1];
var id = cur && cur.length ? cur[0].id : "";
if (lastId !== id) {
lastId = id;
// Set/remove active class
menuItems
.parent().removeClass("active")
.end().filter("[href=#" + id + "]").parent().addClass("active");
}
});
#nav {
width: 100%;
height: 20px;
background-image: url(photos/BG_header2.png);
background-repeat: repeat-x;
display: block;
margin-top: 25px;
margin-left: 390px;
line-height: 17px;
white-space: nowrap;
z-index: 1;
}
#nav2 {
padding-left: 20px;
}
#nav li {
display: inline-block;
margin-top: 0px;
margin-right: 4px;
margin-left: 4px;
margin-bottom: 0px;
text-indent: 3px;
}
#nav a {
color: #006EBE;
width: auto;
text-decoration: none;
font-weight: bold;
font-size: 13px;
font-family: Arial, Helvetica, sans-serif;
text-transform: uppercase;
letter-spacing: 1px;
vertical-align: middle;
-webkit-transition: .5s all ease-out;
-moz-transition: .5s all ease-out;
transition: .5s all ease-out;
}
#nav a:hover {
color: #fff;
}
#nav li.active a {
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul id="nav">
<ul id="nav2">
<li class="active">Accueil
</li>
<li class="trait"></li>
<li>L'entreprise
</li>
<li class="trait"></li>
<li>Services
</li>
<li class="trait"></li>
<li>Jobs
</li>
<li class="trait"></li>
<li>Contact
</li>
</ul>
</ul>
</header>
<a id="anchor1"></a>
<a id="anchor2"></a>
<a id="anchor3"></a>
<a id="anchor4"></a>
Related
I'm looking to make a left to right scrolling navigation menu that's items are highlighted as you scroll down the page. This navigation will look similarly to the following in page navigation on Chase.com (https://www.chase.com/digital/customer-service?jp_cmp=rb/tap/off/na/prt). Please note that I want this navigation to stay scrollable on all devices.
Below is what I have so far. I'm currently having the issue with getting the nav options to scroll into focus as they are highlighted.
window.onscroll = function() {
myFunction()
};
var navbar = document.getElementById("inpagenav");
var sticky = inpagenav.offsetTop;
function myFunction() {
if (window.pageYOffset >= sticky) {
inpagenav.classList.add("sticky")
} else {
inpagenav.classList.remove("sticky");
}
}
// cache the navigation links
var $navigationLinks = $('#inpagenav > ul > li > a');
// cache (in reversed order) the sections
var $sections = $($(".pagenavsection").get().reverse());
// map each section id to their corresponding navigation link
var sectionIdTonavigationLink = {};
$sections.each(function() {
var id = $(this).attr('id');
sectionIdTonavigationLink[id] = $('#inpagenav > ul > li > a[href=\\#' + id + ']');
});
// throttle function, enforces a minimum time interval
function throttle(fn, interval) {
var lastCall, timeoutId;
return function() {
var now = new Date().getTime();
if (lastCall && now < (lastCall + interval)) {
// if we are inside the interval we wait
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
lastCall = now;
fn.call();
}, interval - (now - lastCall));
} else {
// otherwise, we directly call the function
lastCall = now;
fn.call();
}
};
}
function highlightNavigation() {
// get the current vertical position of the scroll bar
var myPadding = $('#inpagenav').height();
var scrollPosition = $(window).scrollTop();
// iterate the sections
$sections.each(function() {
var currentSection = $(this);
// get the position of the section
var sectionTop = currentSection.offset().top;
// if the user has scrolled over the top of the section
if (scrollPosition + myPadding >= sectionTop) {
// get the section id
var id = currentSection.attr('id');
// get the corresponding navigation link
var $navigationLink = sectionIdTonavigationLink[id];
// if the link is not active
if (!$navigationLink.hasClass('active')) {
// remove .active class from all the links
$navigationLinks.removeClass('active');
// add .active class to the current link
$navigationLink.addClass('active');
}
// we have found our section, so we return false to exit the each loop
return false;
}
});
}
$(window).scroll(throttle(highlightNavigation, 100));
// if you don't want to throttle the function use this instead:
// $(window).scroll( highlightNavigation );
.mainimage {
text-align: center;
height: 300px;
background: gray
}
nav {
background: white;
}
.sticky {
position: fixed;
top: 0;
width: 100%;
}
nav ul {
list-style: none;
padding: 0rem;
overflow: auto;
white-space: nowrap;
margin: 0rem;
overflow-x: scroll;
}
nav ul::-webkit-scrollbar-thumb {
background: #000;
}
nav ul li {
padding-top: 1rem;
vertical-align: center;
display: inline-block;
}
nav ul li a {
text-decoration: none;
color: dodgerblue;
display: inline-block;
margin: 0rem 2rem;
padding-bottom: 1rem;
border-bottom: 3px solid transparent;
}
nav ul li a:hover {
color: #0054a4;
border-bottom: 3px solid #0054a4;
}
nav ul li .active {
color: #308ce3;
font-weight: bold;
border-bottom: 3px solid #308ce3;
}
#section1 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: orange;
}
#section2 {
text-align: center;
height: 200px;
padding: 4rem 0rem;
background: green;
}
#section3 {
text-align: center;
height: 300px;
padding: 4rem 0rem;
background: blue;
}
#section4 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: red;
}
#section5 {
text-align: center;
height: 500px;
padding: 4rem 0rem;
background: pink;
}
#section6 {
text-align: center;
height: 500px;
padding: 7rem 0rem;
background: purple;
}
#section7 {
text-align: center;
height: 500px;
padding: 7rem 0rem;
background: purple;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="menu.css">
<body>
<div id="contentwrapper">
<div class="mainimage">
<h1>The whole world</h1>
</div>
<nav id="inpagenav">
<ul>
<li>Section 1</li>
<li>Section 2</li>
<li>Section 3</li>
<li>Section 4</li>
<li>Section 5</li>
<li>Section 6</li>
</ul>
</nav>
<section id="section1" class="pagenavsection">
I'm section 1
</section>
<section id="section2" class="pagenavsection">
I'm section 2
</section>
<section id="section3" class="pagenavsection">
I'm section 3
</section>
<section id="section4" class="pagenavsection">
I'm section 4
</section>
<section id="section5" class="pagenavsection">
I'm section 5
</section>
<section id="section6" class="pagenavsection">
I'm section 6
</section>
<section id="section7">lo</section>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="ScrollMenu.js"></script>
</body>
</html>
You might just need to call $navigationLink.scrollIntoView() when you toggle the active class.
Per this answer, you may need to pass special options to scrollIntoView because the items are laid out horizontally.
$navigationLink.scrollIntoView({ inline: 'end' })
// end is my guess; allowable values are: start, center, end, or nearest (the default)
I am creating a web page with an Index along one side, with anchor links to each relevant section on the page.
Upon loading the page, the first point on the index list is highlighted (different colour), when the user scrolls down manually to another section, I want the corresponding point on the index list to then become highlighted.
So I have a CSS property, to highlight the index point, and this is initially set to the first point on the list.
How can I take this CSS property from one element, and give it to another?
.current {
opacity: 1;
-webkit-transition: opacity 200ms ease;
transition: opacity 200ms ease;
}
This is the CSS applied to the element that should be highlighted. Currently, the first element in the index is always highlighted, but of course, I need it to change as the user scrolls down the page.
Let me know if you need more info.
It is possible with Intersection Observer API .
Example Code using jQuery:
$(window).scroll(function() {
var scrollDistance = $(window).scrollTop();
var threshold=250; //in px
$('section').each(function(i) //list of sections tag to loop
{
if ($(this).position().top-threshold <= scrollDistance && i<4) {
$('.nav-menu li.menu-active').removeClass('menu-active');
$('.nav-menu li').eq(i).addClass('menu-active');
}
});
}).scroll();
Please see this fiddle. https://jsfiddle.net/cse_tushar/Dxtyu/141/
HTML :-
<div class="m1 menu">
<div id="menu-center">
<ul>
<li><a class="active" href="#home">Home</a>
</li>
<li>Portfolio
</li>
<li>About
</li>
<li>Contact
</li>
</ul>
</div>
</div>
<div id="home"></div>
<div id="portfolio"></div>
<div id="about"></div>
<div id="contact"></div>
CSS:-
body, html {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.menu {
width: 100%;
height: 75px;
background-color: rgba(0, 0, 0, 1);
position: fixed;
background-color:rgba(4, 180, 49, 0.6);
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
.light-menu {
width: 100%;
height: 75px;
background-color: rgba(255, 255, 255, 1);
position: fixed;
background-color:rgba(4, 180, 49, 0.6);
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
-o-transition: all 0.3s ease;
transition: all 0.3s ease;
}
#menu-center {
width: 980px;
height: 75px;
margin: 0 auto;
}
#menu-center ul {
margin: 15px 0 0 0;
}
#menu-center ul li {
list-style: none;
margin: 0 30px 0 0;
display: inline;
}
.active {
font-family:'Droid Sans', serif;
font-size: 14px;
color: #fff;
text-decoration: none;
line-height: 50px;
}
a {
font-family:'Droid Sans', serif;
font-size: 14px;
color: black;
text-decoration: none;
line-height: 50px;
}
#home {
background-color: grey;
height: 100%;
width: 100%;
overflow: hidden;
background-image: url(images/home-bg2.png);
}
#portfolio {
background-image: url(images/portfolio-bg.png);
height: 100%;
width: 100%;
}
#about {
background-color: blue;
height: 100%;
width: 100%;
}
#contact {
background-color: red;
height: 100%;
width: 100%;
}
Jquery:-
$(document).ready(function () {
$(document).on("scroll", onScroll);
//smoothscroll
$('a[href^="#"]').on('click', function (e) {
e.preventDefault();
$(document).off("scroll");
$('a').each(function () {
$(this).removeClass('active');
})
$(this).addClass('active');
var target = this.hash,
menu = target;
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
}, 500, 'swing', function () {
window.location.hash = target;
$(document).on("scroll", onScroll);
});
});
});
function onScroll(event){
var scrollPos = $(document).scrollTop();
$('#menu-center a').each(function () {
var currLink = $(this);
var refElement = $(currLink.attr("href"));
if (refElement.position().top <= scrollPos && refElement.position().top + refElement.height() > scrollPos) {
$('#menu-center ul li a').removeClass("active");
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
Please add just active class to the current button (highlight it)
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* Style the buttons */
.btn {
border: none;
outline: none;
padding: 10px 16px;
background-color: #f1f1f1;
cursor: pointer;
font-size: 18px;
}
/* Style the active class, and buttons on mouse-over */
.active, .btn:hover {
background-color: #666;
color: white;
}
</style>
</head>
<body>
<h1>Active Button</h1>
<p>Highlight the active/current (pressed) button.</p>
<div id="myDIV">
<button class="btn">1</button>
<button class="btn active">2</button>
<button class="btn">3</button>
<button class="btn">4</button>
<button class="btn">5</button>
</div>
<script>
// Add active class to the current button (highlight it)
var header = document.getElementById("myDIV");
var btns = header.getElementsByClassName("btn");
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");
current[0].className = current[0].className.replace(" active", "");
this.className += " active";
});
}
</script>
</body>
</html>
You can use the onScroll event to so that a function is triggered when a user scrolls. This can then use scrollTop to get the position.
document.getElementById("idOfScrollingSection").onscroll(() => {
let scrollValue = document.getElementById("elementId").scrollTop;
//Remove class from highlighted item
let oldElement = document.getElementsByClassName("current");
oldElement.classList.remove("current");
//Add highlight class, change values depending on page position
if (scrollValue < 200) {
let elementToBeHighlighted = document.getElementById("idOfElementToBeHighlighted");
elementToBeHighlighted.classList.add("current");
} else if ....
} else {
let elementToBeHighlighted = document.getElementById("idOfElementToBeHighlighted");
elementToBeHighlighted.classList.add("current");
}
})
This is done is pure JS and would be a lot better using jQuery
In my site I made a simple dropdown menu, but my problem is that it won't close if mouseleave happens on the <span> that triggers the dropdown.
Here is my code:
//Find the dropdown span
var header = document.getElementById('drop');
//Find the ul with the links
var ul = document.getElementById('nav-dropdown');
//Get the width and apply it to the dropdown items
var width = drop.getBoundingClientRect().width;
ul.style.minWidth = width + "px";
//Round the corners on the last link
var links = document.getElementsByClassName('dropdown-link');
links[links.length - 1].style.borderRadius = "0 0 7px 7px";
var open = 0;
//Onhover, display the dropdown;
header.addEventListener("mouseover", function() {
ul.style.display = "block";
header.style.borderRadius = "7px 7px 0 0";
if (links[0].getBoundingClientRect().width > width) {
links[0].style.borderRadius = "0 7px 0 0";
}
open = 1;
});
//When the mouse leaves the menu, close it.
ul.addEventListener("mouseleave", function() {
ul.style.display = "none";
header.style.borderRadius = "7px";
open = 0;
});
//What I've tried to fix it:
/*
header.addEventListener("mouseleave", function() {
ul.style.display = "none";
header.style.borderRadius = "7px";
});
*/
/*Stylesheet for this stuff*/
* {
font-family: arial;
margin: 0;
padding: 0;
box-sizing: border-box;
font-size: 20px;
text-decoration: none;
list-style: none;
}
a:visited {
color: white;
}
a,
#drop {
color: white;
}
a:hover {
color: coral;
}
.header-links-container {
position: relative;
top: 0;
background: rgb(63, 83, 95);
width: 100%;
height: 80px;
opacity: .8;
z-index: 999;
}
.title {
font-weight: bold;
font-size: 30px;
padding: 20px 50px;
position: relative;
float: left;
color: white;
}
.header-links {
position: relative;
float: right;
vertical-align: middle;
}
.nav-links {
margin: auto;
padding-top: 20px;
padding-right: 30px;
}
.nav-link {
position: relative;
float: right;
padding: 0 20px;
font-size: 23px;
padding: 5px 10px;
margin: 5px;
background: #4471ba;
border-radius: 7px;
}
.nav-link:hover {
background: #4480ba;
color: #d1d1d1;
}
#nav-dropdown {
display: none;
margin-top: 42px;
margin-left: 5px;
position: absolute;
}
.dropdown-link {
color: black;
background-color: #ccc;
padding: 5px 10px;
}
.dropdown-link:hover {
color: #000;
background-color: #a7a7a7;
}
.dropdown-link:active {
color: white;
background-color: #3b8cfa;
}
<div class="header-links-container">
<h2 class="title">Title</h2>
<div class="header-links">
<ul class="nav-links">
<li class="nav-link">Photo Gallery</li>
<li class="nav-link">SLAP</li>
<li id="drop" class="nav-link"><span>Dropdown</span></li>
<ul id="nav-dropdown" class="jim">
<a href="#">
<li class="dropdown-link">Link 1</li>
</a>
<a href="#">
<li class="dropdown-link">Link 2</li>
</a>
<a href="#">
<li class="dropdown-link">Longer Link</li>
</a>
<a href="#">
<li class="dropdown-link">Vacuum</li>
</a>
</ul>
</ul>
</div>
</div>
<p>
Relavent JS lines start at Line 16
</p>
And here is the fiddle that might make more sense: https://jsfiddle.net/dLw1hu5n/6/
I've tried closing the dropdown like in the last code block, but then it won't stay open when you go to hover over the links. I've also tried making the menu close when the mouse hovers over the navbar div, but no luck there either.
Can I fix this or do I need to start from square 1?
I would prefere to solve this via css. However, in your case you can try the following:
function displayDropdown() {
ul.style.display = "block";
header.style.borderRadius = "7px 7px 0 0";
if (links[0].getBoundingClientRect().width > width) {
links[0].style.borderRadius = "0 7px 0 0";
}
open = 1;
}
function hideDropdown() {
ul.style.display = "none";
header.style.borderRadius = "7px";
open = 0;
}
//Onhover, display the dropdown;
header.addEventListener("mouseover", function() {
displayDropdown();
});
ul.addEventListener("mouseover", function() {
displayDropdown();
});
//When the mouse leaves the menu, close it.
ul.addEventListener("mouseleave", function() {
hideDropdown();
});
header.addEventListener("mouseleave", function() {
hideDropdown();
});
Your JS is fine but your event listener for mouseleave needs to be on the enclosing div. This way your element stays open until you hover outside of the header
t.addEventListener("mouseleave", function() {
ul.style.display = "none";
header.style.borderRadius = "7px";
open = 0;
});
What is t?
var t = document.getElementById(t);
What element has id T?
Try this fiddle to find out https://jsfiddle.net/dLw1hu5n/12/
I'm trying to accomplish a simple effect of sticking the menu to top of the browser window when scrolling passes a certain point, but something went wrong and the menu wont get fixed to the top. From the libraries I'm using jQuery and animate it.
My code is as follows:
HTML:
<nav class="animatedParent">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
CSS:
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
width: 400px;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 35px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
JS (jQuery):
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
});
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
});
var nav = $("nav").offsetTop();
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
console.log('Hello!');
} else {
$("nav").removeClass("fixedNav");
}
});
So first off, you only use the code once, which is when the document is loaded. You're going to want to check everytime you scroll the document as the code should obivously be triggered once you scroll a certain amount.
$(document).scroll(function(){
var nav = $("nav").height();
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
} else {
$("nav").removeClass("fixedNav");
}
});
body {
background: black;
height:700px;
}
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
display: block;
height: 100px;
width: 100%;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 35px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="animatedParent nav">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
You need to use the event scroll and check the offset there.
When the user is scrolling, toggleClass will add/remove the class based on the condition $window.scrollTop() > navOffset which will return true or false
var $window = $(window);
var $nav = $('nav');
var navOffset = $nav.offsetTop();
$window.on('scroll', function() {
$nav.toggleClass('fixedNav', $window.scrollTop() > navOffset);
});
add an scroll event to check your scroll position
for example:
$(document).scroll(()=>{...});
like here
This is a very plain demo, it only demonstrate wha i meant
You can use a library like scrollMonitor to accomplish your task as scroll monitoring have its own caveats.
You can let scrollMonitor to lock position of your menu when it leaves viewport, something like this:
var $menu = document.querySelector('nav'); // It is better to use CSS class name instead
var watcher = scrollMonitor.create($menu);
watcher.lock();
watcher.exitViewport(function() {
$menu.classList.add('fixedNav');
});
watcher.enterViewport(function() {
$menu.classList.remove('fixedNav');
});
Please refer this example as it closely matches your task.
You don't fire the check for the current scroll on scroll event. That's an event you're looking for.
Also you could check the scrollTop on the document (it's more error proof in jQuery), not on the window as it doesn't always work.
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
});
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
});
$(document).on('scroll', function() {
var nav = $("nav").offsetTop();
if($(document).scrollTop() > nav) {
$("nav").addClass("fixedNav");
console.log('Hello!');
} else {
$("nav").removeClass("fixedNav");
}
})
});
That is what you are looking for:
$(document).ready(function(){
$("nav ul li").mouseenter(function() {
$(this).addClass("wiggle");
}) ;
$("nav ul li").mouseleave(function() {
$(this).removeClass("wiggle");
}) ;
});
$(document).ready(fixedHeader) ;
$(window).scroll(fixedHeader) ;
function fixedHeader() {
var nav = parseInt($("nav").css("margin-top")) ;
if($(window).scrollTop() > nav) {
$("nav").addClass("fixedNav");
}
else {
$("nav").removeClass("fixedNav");
}
}
body{
height: 1000px;
}
.fixedNav {
display: block;
position: fixed;
top: 0;
width: 100%;
background: rgba( 0, 0, 0, .8);
height: 100px;
}
nav {
width: 400px;
margin: 20px auto;
}
nav ul {
list-style: none;
}
nav ul li {
float: left;
overflow: auto;
width: 130px;
}
nav ul li a {
font-size: 20px;
font-family: 'Indie Flower', cursive;
color: #fff;
cursor: pointer;
transition: 500ms linear all;
}
nav ul li a:hover {
color: #123456;
transition: 500ms linear all;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="animatedParent">
<ul class="animated bounceInUp delay-750">
<li class="animated">O meni</li>
<li class="animated">Katalog</li>
<li class="animated">Razno</li>
</ul>
</nav>
If a user, using iPhone (actual devices), lands on my website for the first time the "hamburger menu" will not open the menu at all, and navbar will not appear on scrolldown. It seems to be working just fine on Android devices (except maybe Nexus 4 in portrait mode if we were to believe responsinator ), and Win desktops.
The actual website's backend is made with Razor/ASP.NET but obviously I believe this is a pure frontend issue.
After a refresh it starts to work on Apple devices (well, iPhone) as well. And then sometimes stops working (once or twice it stopped working again, I believe).
Head (tried removing async and defer, did not work):
<script type="text/javascript" src="script.js" async defer></script>
Here is HTML (with bad usage of h2 tag with logo image in it):
<div id="navigation-main">
<h2 class="logo">
<a href="#">
<img src="images/white-logo.png" alt="">
</a>
</h2>
<div id="menu-icon">
<span class="icon-menu-hamburguer"></span>
</div>
<nav id="menu-main">
<ul>
<li><a class="scroll" href="#about-anchor">About us</a></li>
<li><a class="scroll" href="#agenda-anchor">Agenda</a></li>
<li><a class="scroll" href="#gallery-anchor">Gallery</a></li>
<li><a class="scroll" href="#sponsors-anchor">Sponsors</a></li>
<li><a class="scroll" href="#contact-anchor">Contact</a></li>
<li>Log in <img src="images/login_icon.png" alt=""></li>
</ul>
</nav>
CSS:
#navigation-main {
min-height: 60px;
z-index: 9;
overflow: hidden;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
#navigation-main:active {
background-color: #000000;
}
#navigation-main .logo {
float: left;
}
#navigation-main .logo img {
display: none;
}
#navigation-main nav {
position: relative;
top: 20px;
}
#navigation-main nav ul {
margin: 0;
padding-left: 0;
}
#navigation-main nav ul li {
list-style: none
}
#navigation-main nav ul li a {
color: #FFFFFF;
text-decoration: none
}
#navigation-main #menu-icon {
display: none;
}
#navigation-main.active {
background-color: rgb(0, 0, 0);
position: fixed;
top: 0;
height: 60px;
width: 100%;
margin-bottom: 0;
-webkit-transition: all 0.5s linear;
-moz-transition: all 0.5s linear;
-ms-transition: all 0.5s linear;
-o-transition: all 0.5s linear;
transition: all 0.5s linear;
}
#navigation-main.active img {
display: inline-block;
}
#navigation-main.active #menu-icon {
top: 10px;
}
#navigation-main.active .logo img {
max-width: 50%;
}
#navigation-main.active nav li a {
color: #FFFFFF
}
#navigation-main nav ul li img {
vertical-align: middle;
}
#media (max-width: 768px) {
#navigation-main .logo img {
max-width: 80%
}
#navigation-main #menu-icon {
padding: 18px 12px;
margin: 2px 0;
position: relative;
top: 20px;
display: block;
float: right;
z-index: 10;
cursor: pointer;
}
#navigation-main #menu-icon .icon-menu-hamburguer {
background: #ff0000;
width: 30px;
height: 4px;
margin: 2px 0;
display: block;
}
#navigation-main #menu-icon .icon-menu-hamburguer:after,
#navigation-main #menu-icon .icon-menu-hamburguer:before {
content: '';
background: #ff0000;
width: 30px;
height: 4px;
display: block;
margin: 2px 0;
position: relative;
}
#navigation-main #menu-icon .icon-menu-hamburguer:before {
bottom: 8px;
}
#navigation-main #menu-icon .icon-menu-hamburguer:after {
top: 2px;
}
#navigation-main nav {
display: none;
width: 100%;
}
#navigation-main nav.menu-active {
display: block;
clear: both;
height: 100%;
position: fixed;
z-index: 1;
left: 0;
top: 0;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.80);
overflow-x: hidden;
}
#navigation-main nav.menu-active ul {
position: relative;
top: 15%;
width: 100%;
text-align: center;
margin-top: 30px;
}
#navigation-main nav.menu-active a {
padding: 8px;
text-decoration: none;
font-size: 1.75rem;
display: block;
}
}
#media (min-width: 768px) {
#navigation-main nav {
float: right;
padding-right: 20px;
}
#navigation-main nav ul li,
#navigation-main nav ul li img {
display: inline-block;
}
#navigation-main nav ul li a {
padding: 0 5px;
font-size: 0.9rem;
}
}
Javascript:
(function() {
////////// Sticky navbar and hamburger icon
var headerScroll = getId('navigation-main'),
scrollHeight = 250,
menuIcon = getId('menu-icon'),
menuMain = getId('menu-main'),
classMenu = 'menu-active',
classHeader = 'active';
// Scroll
window.addEventListener("scroll", scrollOn);
function scrollOn() {
animatedScroll(headerScroll, classHeader, scrollHeight);
}
// Responsive menu
menuIcon.onclick = function() {
toggle(menuMain, classMenu);
}
menuMain.onclick = function() {
toggle(menuMain, classMenu);
}
// Moving the element after scrolling
function animatedScroll(element, classN, height) {
y = pageYOffset;
if (y > height) {
element.className = classN;
} else {
element.className = '';
}
}
// Change the element's class
function toggle(element, classe) {
element.className = element.className ? '' : classe;
}
// Return the element
function getId(id) {
return document.getElementById(id);
}
////////// Sticky navbar and hamburger icon
// Feature Test
if ('querySelector' in document && 'addEventListener' in window && Array.prototype.forEach) {
// Function to animate the scroll
var smoothScroll = function(anchor, duration) {
// Calculate how far and how fast to scroll
var startLocation = window.pageYOffset;
var endLocation = anchor.offsetTop;
var distance = endLocation - startLocation;
var increments = distance / (duration / 16);
var stopAnimation;
// Scroll the page by an increment, and check if it's time to stop
var animateScroll = function() {
window.scrollBy(0, increments);
stopAnimation();
};
// If scrolling down
if (increments >= 0) {
// Stop animation when you reach the anchor OR the bottom of the page
stopAnimation = function() {
var travelled = window.pageYOffset;
if ((travelled >= (endLocation - increments)) || ((window.innerHeight + travelled) >= document.body.offsetHeight)) {
clearInterval(runAnimation);
}
};
}
// If scrolling up
else {
// Stop animation when you reach the anchor OR the top of the page
stopAnimation = function() {
var travelled = window.pageYOffset;
if (travelled <= (endLocation || 0)) {
clearInterval(runAnimation);
}
};
}
// Loop the animation function
var runAnimation = setInterval(animateScroll, 16);
};
// Define smooth scroll links
var scrollToggle = document.querySelectorAll('.scroll');
// For each smooth scroll link
[].forEach.call(scrollToggle, function(toggle) {
// When the smooth scroll link is clicked
toggle.addEventListener('click', function(e) {
// Prevent the default link behavior
e.preventDefault();
// Get anchor link and calculate distance from the top
var dataID = toggle.getAttribute('href');
var dataTarget = document.querySelector(dataID);
var dataSpeed = toggle.getAttribute('data-speed');
// If the anchor exists
if (dataTarget) {
// Scroll to the anchor
smoothScroll(dataTarget, dataSpeed || 500);
}
}, false);
});
}
})();
And here is JSFiddle.
If it's touchstart/onclick issue why does it work after the refresh? Should I remove IFFE? Should I put script tag at the end of the page?
What seems to be the issue here?
Apparently the line in the header was an issue.I have removed "async" and the navigation menu started working.
<script type="text/javascript" src="script.js" async defer></script>
changed to:
<script type="text/javascript" src="script.js" defer></script>