Change navigation active class on window scroll
DEMO
Serlite's code is very good but had some bugs.
- If you scroll down to the end last two
a
elements haveactive
class so both are highlighted.
Solution
added $('#menu-center ul li a').removeClass("active");
to remove all previous active class before adding new class in the below code.
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"); //added to remove active class from all a elements
currLink.addClass("active");
}
else{
currLink.removeClass("active");
}
});
}
- If you click on 2nd or greater menu link it makes you scroll to the location but changes active class to previous link.
Solution
$('html, body').stop().animate({
'scrollTop': $target.offset().top+2
change the active list when scrolling navbar
The first problem with your code is that you're not calling the "activeLink" function correctly.
if(top >= offset && top < offset + height){
lists.forEach(sec =>{
activeLink;
})
}
If you add the parentheses, then it'll work and throw an error due to the "this" keyword which refers to the window object in this case.
To work, in the "onScroll" handler, you can replace your code with this piece:
if (top >= offset && top < offset + height) {
lists.forEach((item) => {
item.classList.remove('active');
if(item.querySelector('a').getAttribute('href') == '#' + id){
item.classList.add('active');
}
});
}
Of course, your aim will be not to duplicate your code. So, we can first select the target like that:
const target = document.querySelector(`[href='#${id}']`).parentElement;
activeLink(target);
Passing it to the "activeLink" function directly will lead you to check the coming parameter if it is the "click event" or the list item and handles both cases. instead, you can edit your handler code like this:
lists.forEach((item) =>
item.addEventListener('click', function(){
activeLink(this);
}));
And this is the "activeLink" function code in the final state:
function activeLink(li) {
lists.forEach((item) => item.classList.remove('active'));
li.classList.add('active');
}
Here is the code snippet for this:
let section = document.querySelectorAll('section');
let lists = document.querySelectorAll('.list');
function activeLink(li) {
lists.forEach((item) => item.classList.remove('active'));
li.classList.add('active');
}
lists.forEach((item) =>
item.addEventListener('click', function(){
activeLink(this);
}));
window.onscroll = () => {
section.forEach(sec => {
let top = window.scrollY;
let offset = sec.offsetTop;
let height = sec.offsetHeight;
let id = sec.getAttribute('id');
if (top >= offset && top < offset + height) {
const target = document.querySelector(`[href='#${id}']`).parentElement;
activeLink(target);
}
})
};
.sec {
height: 500px;
}
nav {
position: fixed;
width: 100%;
top: 0;
left: 0;
z-index: 10;
background-color: #fff;
}
.active a {
color: palevioletred;
}
<nav class="navigation">
<ul>
<li class="list active">
<a href="#home">
<span class="icon">
<ion-icon name="home-outline"></ion-icon>
</span>
<span class="title">Home</span>
</a>
</li>
<li class="list">
<a href="#about">
<span class="icon">
<ion-icon name="person-outline"></ion-icon>
</span>
<span class="title">About Me</span>
</a>
</li>
<li class="list">
<a href="#working">
<span class="icon">
<ion-icon name="newspaper-outline"></ion-icon>
</span>
<span class="title">Working</span>
</a>
</li>
<li class="list">
<a href="#Learned">
<span class="icon">
<ion-icon name="code-slash-outline"></ion-icon>
</span>
<span class="title">Learned</span>
</a>
</li>
<li class="list">
<a href="#contact">
<span class="icon">
<ion-icon name="chatbox-outline"></ion-icon>
</span>
<span class="title">Contact</span>
</a>
</li>
</ul>
</nav>
<section class="sec" style="background-color: beige;" id="home"></section>
<section class="sec" style="background-color: yellow;" id="about"></section>
<section class="sec" style="background-color: orange;" id="working"></section>
<section class="sec" style="background-color: orangered;" id="Learned"></section>
<section class="sec" style="background-color: olive;" id="contact"></section>
jquery scroll, change navigation active class as the page is scrolling, relative to sections
If you wish a more generic function:
SEE DEMO
$(window).scroll(function() {
var windscroll = $(window).scrollTop();
if (windscroll >= 100) {
$('nav').addClass('fixed');
$('.wrapper section').each(function(i) {
if ($(this).position().top <= windscroll - 100) {
$('nav a.active').removeClass('active');
$('nav a').eq(i).addClass('active');
}
});
} else {
$('nav').removeClass('fixed');
$('nav a.active').removeClass('active');
$('nav a:first').addClass('active');
}
}).scroll();
How to keep class active when scrolling with javascript?
Something like this? I couldn't reproduce the flickering visually on my machine but I can see the class being removed/added constantly on scroll
https://jsfiddle.net/7szpuqsr/1/
Main changes, I added a class to your sections, you have too many sections but with the way your code is meant to work, it's much easier to add a class to the sections, example below
<section id="home" class="section">
var sections = $('.section')
to get the section class
updated this part of the js to check for active class
if (cur_pos >= top && cur_pos <= bottom) {
if(!$(this).hasClass("active")) {
nav.find('a').removeClass('active');
sections.removeClass('active');
$(this).addClass('active');
nav.find('a[href="#'+$(this).attr('id')+'"]').addClass('active');
}
}
You can also cache the $(this)
into a variable inside of the section loop like
var $this = $(this);
then just use $this
for the rest of the loop
here is the doc for hasClass
https://api.jquery.com/hasclass/
Related Topics
How to Use CSS Calc Within JavaScript
Performance Difference Between JavaScript Created Inline Styles and JavaScript Created Stylesheets
Scroll to Bottom in Chat Box in Angularjs
Greek and Text-Transform:Uppercase
Implementing Transition Effects in React Js When State Changes
Fastest Way to Preload/Load Large Images
Uncaught Typeerror: Cannot Read Property 'Classname' of Undefined
Prevent Requestanimationframe from Running All the Time
How to Use Jquery to Detect If a File Input Has a File Selected
Navigate to Screen After Opening a Notification
Resize Jqgrid Based on Number of Rows
Jqm Ui-Content 100% Height Issue
CSS :Hover on Mobile or Other Device as Toggle
Bootstrap Progress Bar Progression
How to Make React-Bootstrap's Dropdown Open on Mouse Hover
Make Named Anchor Bookmarks Appear Always at Top of the Screen When Clicked