Update the scrollspy navigation in a div with overflow by toggling the active class

Struggling to implement a navigation menu within a self-scrolling div using html/css/jquery. Looking for the menu items to toggle the active class when in view or at the top of the scrolling div.

I'm essentially trying to achieve something like this example: https://codepen.io/vlrprbttst/pen/LkjZbE?editors=1010, but contained within a self-scrolling div.

I've made progress with this code pen: https://codepen.io/frontend2020/pen/ExWaXVE, however, the active class triggers prematurely and I can't seem to pinpoint why.

I suspect there may be an issue in the following section of code:

if (
      refElement.position().top <= scrollPos &&
      refElement.position().top + refElement.height() > scrollPos
    )

I've checked the scroll position and element positions, everything seems aligned, yet I feel I might be overlooking something crucial.

Any guidance or solution would be greatly appreciated. Thank you!

Answer №1

If you're searching for a way to implement a scrollspy, you've come to the right place.

To achieve this, you will need to attach an event listener to the document. As the user scrolls, iterate through each section to determine if it is currently visible on the screen. If it is, apply a specific class to the corresponding navigation element. If not, remove the class.

This concept can be illustrated as follows:

$(document).ready(function() {
  function isInViewport(elem) {
    if (typeof jQuery === "function" && elem instanceof jQuery) {
      elem = elem[0];
    }
    var bounds = elem.getBoundingClientRect();
    return (
      bounds.top >= 0 &&
      bounds.left >= 0 &&
      bounds.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
      bounds.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
  }
  var sections = $('.section');
  $(document).scroll(function() {
    for (let i = 0; i < sections.length; i++) {
      let currentSection = sections[i];
      let relatedNav = $('li[data-id="' + $(currentSection).data('for') + '"');
      if (isInViewport(currentSection)) {
        relatedNav.addClass('active');
      } else {
        relatedNav.removeClass('active');
      }
    }
  })
})
.section.first {
  margin-top: 100px;
}

.section {
  height: 500px;
  border: 1px solid;
}

.nav {
  position: fixed;
  top: 0;
}

.nav .active {
  background-color: #ff4a4a;
  color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav">
  <ul>
    <li data-id="1">Section 1</li>
    <li data-id="2">Section 2</li>
    <li data-id="3">Section 3</li>
  </ul>
</div>
<div class="section first scrollspy-target" data-for="1">
  Section 1
</div>
<div class="section scrollspy-target" data-for="2">
  Section 2
</div>
<div class="section scrollspy-target" data-for="3">
  Section 3
</div>

Note: I suggest trying out the live demo here.

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

Send two arguments to a personalized validation function using express-validation

I have a requirement to input two values in order to search for a subdocument using the main document ID and then another ID of the subdocument. These IDs are received as parameters, and I am utilizing express-validator with a custom function to ensure th ...

Issue: Attempting to render objects as React children is invalid. Consider using an array if you want to render a collection of children. This problem often occurs when fetching data from a JSON

Hey everyone, I'm currently working on a small website using ReactJS. After adding the code below, an error keeps popping up: Objects are not valid as a React child. If you meant to render a collection of children, use an array instead. Here's t ...

Unable to implement a design on a button during its click event

I successfully implemented a dynamic button in HTML5 and Javascript. The button has a click event assigned to it, so when clicked, its content and background color are supposed to change. However, while the content changes correctly, the background color d ...

Working with AngularJS: Implementing a Service in a Controller

A service has been developed in AngularJS, but it is not being utilized in the controller. Service.js var appService = angular.module("appService", []); appService.service("bddService", function() { var bdds = bdd; this.getBdds = function(){ ...

Ways to ensure certain code is executed every time a promise is resolved in Angular.js

Within my Angular.js application, I am executing an asynchronous operation. To ensure a smooth user experience, I cover the application with a modal div before initiating the operation. Once the operation is complete, regardless of its outcome, I need to r ...

AngularJS directive that performs asynchronous validation upon blur

I'm working on developing a directive that validates email addresses provided by users through asynchronous web requests. While the functionality is sound, I've encountered an issue where asynchronous calls are triggered every time a user types a ...

multiple elements sharing identical CSS styling

For each component, I made separate CSS files and imported them accordingly. However, despite the individual styling efforts, all components seem to have the same appearance. I specifically worked on styling an image differently for two components, but w ...

Having trouble getting a local npm installation to work from a specific file path?

After following the instructions from this helpful link to install an npm package through a file path, I encountered an error when attempting to use it: Cannot find module '<module_name>' or its corresponding type declaration Are there an ...

React Table in Modal Using Custom Hook State

I'm facing some difficulties with the React useState hook. Currently, I have a modal that pops up after submitting a form. Before loading the modal, the application calls an API to fetch data, which is then displayed in a table within the modal. The ...

Sharing data between two Angular 2 component TypeScript files

I'm facing a scenario where I have two components that are not directly related as parent and child, but I need to transfer a value from component A to component B. For example: In src/abc/cde/uij/componentA.ts, there is a variable CustomerId = "sss ...

Dealing with Memory Leaks in AngularJS and Jquery

My web application has been created with a combination of jQuery and Angularjs. I am currently on the lookout for patterns that could lead to memory leaks in Angularjs. I have used Chrome profiler as a tool to find memory leaks, but unfortunately haven&a ...

Utilize jQuery to export HTML or JSON data to an Excel spreadsheet

I am looking for a way to export json or html data to an excel sheet using only html and jquery, without involving any server code. I have found some fiddles that allow me to download the excel sheet successfully, but unfortunately, none of them work in In ...

Having trouble with React's conditional rendering not working as expected?

I am currently working on updating the contents of my Navbar and Router by using useContext and conditional rendering techniques. Here is a snippet from my App.js: import "./App.css"; import axios from "axios"; import { AuthContextProv ...

Sending a series of filtered GET requests to my Express backend in a MERN (MongoDB, Express, React,

I have developed a MERN web application and am in the process of adding some GET methods to retrieve the same item for different scenarios. However, when I attempt to implement a second filter method and pass an existing parameter in my item schema, Postma ...

Decreased Performance in Vue Threejs with Larger JSON Data Sets

I am currently upgrading a legacy Three.js project from Angular 1.5 to Vue 2.6. The project is used for visualizing objects in JSON file format and I'm experiencing a drop in frame rate, going from ~60FPS in Angular to ~12FPS in Vue when loading large ...

Navigating the world of gtag and google_tag_manager: untangling

Tracking custom events in my react application using Google Analytics has been successful. Initially, I followed a helpful document recommending the use of the gtag method over the ga method for logging calls. The implementation through Google Tag Manager ...

Having trouble verifying the selection option in Angular 6

I've been trying to implement Select option validation in Angular 6, but neither Aria-required nor required seem to be effective. The requirement is for it to display a message or show a RED border similar to HTML forms. Here's the HTML snippet ...

How can I show the text name as a selection in the React Material UI Autocomplete component while sending the ID as the value?

Material UI Autocomplete component functions properly, but I am interested in extracting object.id as the value for the onSelect event (rather than object.name). Essentially, I want to display the object.name as the select item label, while retrieving obje ...

How to retrieve TypeScript object within a Bootstrap modal in Angular

Unable to make my modal access a JavaScript object in the controller to dynamically populate fields. Progress Made: Created a component displaying a list of "person" objects. Implemented a functionality to open a modal upon clicking a row in the list. ...

A method to find the sum of the final n elements in an array by employing Arr.reduceRight

I have successfully calculated the sum of the last n elements in an array using a for loop. Is it possible to achieve the same result using Arr.reduceRight instead? x = [1,2,3,4,5]; y = 0 for(let i=x.length; i>x.length-3; i--) { console.log(x[i-1]); ...