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

The compilation process encountered an error: TypeError - Unable to access property 'exclude' as it is undefined (awesome-typescript-loader)

After successfully converting my existing Angular 2 project into Angular 4, I encountered the following error: Module build failed: TypeError: Cannot read property 'exclude' of undefined For more details, please refer to the attached image bel ...

A problem arises when trying to showcase the content in a responsive manner on the hamburger menu, particularly when viewing on mobile

As a newcomer to web development, I decided to challenge myself by building an E-Commerce website to enhance my skills. To ensure mobile responsiveness, I opted for a hamburger menu to hide the navbar content. However, despite resizing working flawlessly, ...

Issue encountered when utilizing ngResource in factory: unable to choose JSON index

ngResource in a factory is functioning properly, but unfortunately, it is only able to select the index of the JSON. However, it is also possible to bind the same variable $scope.resultItems. The console log appears as follows ...

Ensure that the anchor element's height fills the entire div when using the display:block property

My HTML code is very simple: <div class='mydiv'> <a href='#'>Link</a> <div> As for the CSS: div.mydiv { height: 200px; width: 200px; background-color:red; } div.mydiv a { display:block; color:yellow; b ...

An array of dictionaries that are the same except for one dictionary containing an unspecified key

A while ago, I wrote some sample code to generate Euler diagrams from an array of dictionaries. Strangely enough, it only works when the array is explicitly defined in my .js file; using input from a .json file to construct it incrementally does not yield ...

Searching for and removing array elements in Angular 2 using the IndexOf method

Hey there! I'm currently in the process of trying to remove a specific item from my array while working with Angular2 and Typescript. My goal is to identify the index based on the value provided. The array I am working with is initialized as follows. ...

Discovering the server endpoint for the Star Wars SWAPI API: a step-by-step guide

I have been working on integrating a search query into the server-side endpoint, which interacts with swapi - the Star Wars API https://swapi.co/ to display a list of people by their names. Below is the fetch call made to the backend in App.js file using ...

Utilizing ES6 promises in node.js to send a null response

I'm looking for assistance on how to execute a query using ES6 native promises in node.js. The code I have below is what I've been working with: let arr= []; conn.query('select * from table1', (err, b) => { for (let i = 0; i ...

Automatically fill in a text box with previously saved information

Does anyone have suggestions on how to create this type of textbox or what it is called? (View original image here) ...

The Firebase 'not-in' operator is malfunctioning

Within my database, there is a document located at: https://i.stack.imgur.com/OTZpd.png I am attempting to query the number of messages documents where the user's ID does not appear in the "read_by" array. This is the code I am currently using: const ...

Issue with Flex display not being applied within Material UI Grid Item

I am attempting to position an element at the end of a Grid Item (horizontally). In order to achieve this, I am enclosing my component in the following div: Here is the complete code snippet: <Grid container spacing={8} alignItems={'stretch' ...

Issues arising from jQuery dialog functionality when trying to link specific IDs

Having little to no experience with JavaScript, I came across a code snippet on jQuery's website that I am using. Here is the code: $(function(){ $("a").on('click', function(e){ e.preventDefault(); $('<div/>&ap ...

The try and catch block in JavaScript is failing to correctly capture the HTTP status

I have a function that successfully posts JSON to an API endpoint. Here is the code I am using: function sendValuesPageLoad(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function () { try { if (xhr.readyState === ...

Designing a visual showcase with interactive tab links for image selection

I have been working on developing an Angular component that simulates a tab gallery functionality, inspired by this example. Below is my HTML structure: <div class="gallery-container"> <div class="display-container"> ...

Could you share the most effective method for implementing a live search feature using javascript or jquery?

While attempting to create a live search for a dataset containing over 10,000 rows, I specified the DOM structure that is available. Despite my efforts to check each result after a single input during the live search process, my browser keeps hanging. Is t ...

Numerous input fields available for AJAX auto-complete functionality and name verification

Currently, I am working on implementing a text box that will search through a mysql database and display auto-completed text below the input field. Additionally, I want to include a visual indicator like a confirmation tick or cross to signify whether the ...

Having trouble getting a DIV to appear on top of another DIV containing an image

I need help with positioning an "InfoBox" above the main header image on my website. Despite trying z-indexes and adjusting position, I can't seem to get it right. If anyone has any suggestions, please share. Thank you! For reference, here is the HTM ...

Update the image links to automatically refresh every half a second based on the values inputted in the text bars

Is there a better and simpler way to define AAAAAAAAAA, BBBBBBBBBB, and CCCCCCCCCC using the links provided in the text bars named chart1, chart2, and chart3? This learning project is being done through Notepad++ for personal use only, with no need to sa ...

How to target and append individual table cells to a particular table row using JQuery

Here is a snippet of code to consider: <tbody> <tr class="wsui-table-row-odd"> <td>IamaTextFieldBox</td> <td class="im-label-required">Label required</td> </tr> <tr class="wsui-table-row ...

How can a React app be developed offline?

I am currently working offline with no access to the internet. Node.js is already installed on my system, but I encountered an error when trying to run the command npm create-react-app. Is there a way for me to execute npm commands and set up a react app ...