Creating interactive navigation bar effects with scroll and click functionality using jQuery

Is there a way to make the navigation highlight when a user clicks on it and also scrolls to the corresponding section? Currently, I am facing an issue where only the third navigation event highlights, most likely because when navigating to the fourth or fifth event the scroll bar is already at the bottom of the page. This causes events 4 and 5 to never reach the top, resulting in only event 3 being highlighted. I have tried using if statements to check if the clicked event is at the top and if the scrollbar is not at the bottom, but with no success.

To better demonstrate the issue, you can view this example. Clicking on option 5 does not trigger highlighting as expected.


$('.option').children('a').click(function() {
    $('.option').css('background-color', '#CCCCCC;');
    $(this).css('background-color', 'red');
    var postId = $($(this).attr('href'));
    var postLocation = postId.offset().top;
    $(window).scrollTop(postLocation);
});
$(window).scroll(function() {
    var scrollBar = $(this).scrollTop();
    var allPosts = [];
    var lastPost = allPosts.length - 1;
    var windowHeight = $(window).height();
    var bottomScroll = windowHeight - scrollBar;
    
    $(".content").each(function(){            
        allPosts.push($(this).attr('id'));
    });

    for(var i = 0; i < allPosts.length; i++) {
        var currentPost = "#" + allPosts[i];
        var postPosition = $(currentPost).offset().top;
        
        if (scrollBar >= postPosition){
            $('.option').css('background-color', '#CCCCCC');
            $('#nav' + allPosts[i]).css('background-color', 'red');
        }; 
    }; 
}); 

Answer №1

It seems like the scroll() handler is a bit too complicated. To simplify, you just need to check if the scrollbar or scrollTop reaches the top offset value of '.contents' without exceeding its total height (offset().top plus height()).

$(window).scroll(function () {
    var scrollBar = $(this).scrollTop();

    $(".content").each(function (index) {
        var elTop = $(this).offset().top;
        var elHeight = $(this).height();

        if (scrollBar >= elTop - 5 && scrollBar < elTop + elHeight) {
            /* $(this) '.content' is currently visible on the viewport,
               you can target the corresponding navigation item by getting its index,
               for example - $('.Nav li').eq(index)    
            */
        }
    });
});

In addition, there's no need to explicitly set

$(window).scrollTop(postLocation);
because the default behavior of <a> tag anchors works when clicked. If you want to animate the scrolling instead, make sure to prevent the default anchor behavior first:

$('.option').children('a').click(function (e) {
    e.preventDefault();
    var postId = $($(this).attr('href'));
    var postLocation = postId.offset().top;

    $('html, body').animate({scrollTop:postLocation},'slow');
});

Feel free to check out the demo.

Answer №2

Have you considered using Bootstrap's Scrollspy feature instead of trying to create it from scratch? It's a simple and efficient way to implement this functionality without reinventing the wheel.

For implementation steps, check out this link.

If you want to see a demonstration, take a look at this example. You'll notice that only one line of JavaScript is needed!

$('body').scrollspy({ target: '.navbar-example' });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can you transform a nested array into a flat JavaScript map?

If we consider a JavaScript Map structured like this: [ { id: 1, name: "Foo", contents: [1,2,3], morecontents: ["a","b"], }, { id: 2, name: "Bar", c ...

The error message states: "TypeError: a.map is not a function"

I recently deployed my React JS app on Heroku and encountered some issues with the routing. While everything worked smoothly on my local host, I faced errors after fixing the routing problem that I couldn't resolve. Despite extensive research, I haven ...

Could not connect: AJAX Request denied?

I am currently hosting a Digital Ocean server that runs on a MEN stack composed of MongoDB, Express, and Node. The registration form can be accessed at: When attempting to choose an option from the dropdown menu, I encounter the following error message: G ...

Configuring the Port for NodeJS Express App on Heroku

Currently, I am in the process of hosting my website on Heroku and configuring everything to ensure my app is up and running smoothly. However, each time I attempt to submit the form, undefined errors occur. For more details on the Undefined Errors and Co ...

Tips for waiting for an event from a specific element in Playwright

Is there a way to await an event on a specific element using Playwright? Similar to page.waitForEvent, but focusing only on a particular element rather than the entire page. More information can be found in the documentation. ...

What are the best ways to make this date more visually appealing and easy to understand?

Hey there! So I have a date that looks like this: 2022-06-28T17:09:00.922108+01:00 I'm trying to make it more readable, but unfortunately, when I attempted using moment-js in my javascript/react project, it threw an error stating "invalid format". ...

Choosing multiple options from a list

I am working on a messaging app where users can compose and send messages to contacts. Currently, I am only able to send messages to one contact at a time. My goal is to enable users to select multiple contacts to create group messages. Since I am new to a ...

Unable to display Apexcharts bar chart in Vue.js application

Struggling to incorporate Apexcharts into my Vue.js site, but unfortunately, the chart isn't appearing as expected. -For more guidance on Apexcharts, check out their documentation Here HTML <div class="section sec2"> <div id="chart" ...

Encountering an issue with jQuery ajax when attempting to make a post

I am having trouble making a rest service call from JQuery ajax using the POST method. Below is my code: <!DOCTYPE html> <html> <head> <script src="lib/js/jquery/jquery-1.7.2.min.js"></script> </head> <body> & ...

Following an AJAX request, jQuery.each() does not have access to the newly loaded CSS selectors

Note: While I value the opinions of others, I don't believe this issue is a duplicate based on the provided link. I have searched for a solution but have not found one that addresses my specific problem. Objective: Load HTML content to an element u ...

Guide to showcasing user input using a Javascript function

I need assistance to show the user input via the submit button. Users will enter tool types and the first five inputs will be displayed in list items (li). Once the limit of 5 tools is reached, a message 'Thanks for your suggestions' should appea ...

Adding a trailing slash to the URL in an Express server causes it to be appended

I've encountered a strange issue with my express server. Whenever I try to use a specific URL route with the word 'bind,' an extra '/' is automatically added to it. This behavior isn't happening with other URLs that I've ...

Update the message displayed in the user interface after the view has been fully rendered in an Express application, following the execution of asynchronous

I have created a simple express app that reads files from a directory, renames them, zips the files asynchronously, and then renders another view. The file reading and renaming are done synchronously, while the zipping part is handled asynchronously. My cu ...

How shouldjs makes value verification effortless for unordered arrays

In my express.js application, I'm currently using supertest and should.js as my preferred testing framework. However, I've encountered some difficulties when it comes to testing for specific values within an unordered array. After referring to t ...

I'm experiencing an issue with loading the GeoJSON file on my localhost

I included this vector into my local host code, but the JSON file does not seem to load. geojson_layer = new OpenLayers.Layer.Vector("features", { projection: epsg4326, strategies: [new OpenLayers.Strategy.Fixed()], pro ...

Is it possible for a div with fixed position to still have scrolling functionality

My fixed positioned div (#stoerer) appears to be moving while scrolling, although it is just an optical illusion. Check out this visual explanation: view gif for clarification Below is the code snippet in question: <div id="stoerer"> <button ...

How do I save basic information to a MySQL database with JQuery/AJAX in Symfony?

I am currently trying to save a basic piece of data (the file title) within a div element into a MySQL database. Can anyone help me identify any errors in my code? Below is the script I am using: $( document ).ready(function() { $( "#store-button" ). ...

Parent's hover element

I am currently working with the following loop: <?php if( have_rows('modules') ): $counter = 0; while ( have_rows('modules') ) : the_row(); ?> <div class="col span_4_of_12 <?php if($counter == 0) { ?>firs ...

Issues arising during the initialization of Tinymce

After setting the editor on the frontend, I encountered an issue with initializing tinymce. Here is my code: <head> <script src="//cdn.tinymce.com/4/tinymce.min.js"></script> </head> <body> <a class=pageedit>Edit< ...

The PKIJS digital signature does not align with the verification process

Explore the code snippet below const data = await Deno.readFile("./README.md"); const certificate = (await loadPEM("./playground/domain.pem"))[0] as Certificate; const privateKey = (await loadPEM("./playground/domain-pk ...