What's the best way to update the menu element colors as I scroll down the page?

I am looking to update the color scheme of menu elements as the page scrolls using the provided template. I tried a few methods, but they lack dynamism. How can I make it more dynamic?

$(document).ready(function(){

//scroll animation

$('.navigation a').on('click',function(){ 

var target = $(this);
var element = target.attr('href');

$('.navigation a').removeClass('active');
target.addClass('active');

navHeight = $(".navigation").height();

    $("body, html").animate({ 
      scrollTop: $( element ).offset().top + navHeight - 120 
    }, 800);
});

 //updating menu element colors while scrolling

 $(window).scroll(function() {

 var scrollTop = $(document).scrollTop();

 if(scrollTop < 1000) {
 $(".navigation a").removeClass('active');
 $("a[title='About']").addClass('active');
 }
 else if(scrollTop > 1001 && scrollTop < 2000) {
 $(".navigation a").removeClass('active');
 $("a[title='Work']").addClass('active');
 }
 else if(scrollTop > 2001 && scrollTop < 3000) {
 $(".navigation a").removeClass('active');
 $("a[title='Clients']").addClass('active');
 }
 else if(scrollTop > 3001 && scrollTop < 4200) {
 $(".navigation a").removeClass('active');
 $("a[title='Blogs']").addClass('active');
 }
 else if(scrollTop > 4200 && scrollTop < 4600) {
 $(".navigation a").removeClass('active');
 $("a[title='Contact']").addClass('active');
 }
  });
});
* {
list-style-type: none;
padding: 0;
margin: 0;
}

body {
font-size: 16px;
background: #eee;
padding-top: 90px;
font-family: 'Roboto',Arial, Helvetica, Sans-serif;
overflow-x: hidden;
}

.navigation {
top: 0;
left: 0;
padding: 0 10%;
width: 100%;
position: fixed;
color: #fff;
box-sizing: border-box;
background: #363636;
text-align: center;
}
.navigation a {
color: inherit;
margin: 35px 5px;
line-height: 150%;
padding: 0 5px 0 20px;
display: inline-block;
text-decoration: none;
border-left: 1px solid #fff;
}

.navigation a.active { color: yellow;}
.navigation a:first-child { border: 0; }
.box {
width: 100vw;
height: 100vh;
font-size: 14vw;
padding-top: 100px;
text-align: center;
background: #4CD2DA;
}
.box:nth-child(2) { background: #59DAE2; }
.box:nth-child(3) { background: #4372A6; }
.box:nth-child(4) { background: #D8E0E3; }
.box:nth-child(5) { background: #4B565A; }
<html>
<head>
<title>ScrollSpy</title>
<link rel="stylesheet" type="text/css" href="scrollspy.css">
</head>
<body>
<nav class="navigation">
<a class="active" href="#about" title="About">About</a>
<a href="#work" title="Work">Work</a>
<a href="#clients" title="Clients">Clients</a>
<a href="#blogs" title="Blogs">Blogs</a>
<a href="#contact" title="Contact">Contact</a>
</nav>

<div id="container">
<div id="about" class="box">
About

</div>
<div id="work" class="box"gt;
Work
</div>
<div id="clients" class="box">
Clients
</div>
<div id="blogs" class="box">
Blogs
</div>
<div id="contact" class="box">
Contact
</div>
</div>

<script src="https://code.jquery.com/jquery-3.2.0.min.js"></script>
<script type="text/javascript" src="scrollspy.js"></script>


</body>
</html>

view codepen example here

Answer №1

To highlight the menu item corresponding to the box being scrolled to, you can calculate the position of each box on the page and add the "active" class to the respective navigation item.

For a visual demonstration, check out the snippet below or visit this jsFiddle link

$(document).ready(function() {

  // Smooth scrolling animation
  
  $('.navigation a').on('click', function() {
    var target = $(this);
    var element = target.attr('href');
    
    $('.navigation a').removeClass('active');
    target.addClass('active');
    
    navHeight = $(".navigation").height();
    
    $("body, html").animate({
      scrollTop: $(element).offset().top + navHeight - 120
    }, 800);
  });

  // Change color of navigation items based on scroll position

  $(window).scroll(function() {
    var scrollTop = $(document).scrollTop();
    
    $(".box").each(function() {
      var id = $(this).attr("id");
      var height = $(this).outerHeight();
      var oTop = $(this).offset().top - 120;
      
      if (scrollTop > oTop && scrollTop < oTop + height) {
        $(".navigation a[href='#" + id + "']").addClass("active");
      } else {
        $(".navigation a[href='#" + id + "']").removeClass("active");
      }
    });
  });

});

* {
  list-style-type: none;
  padding: 0;
  margin: 0;
}

body {
  font-size: 16px;
  background: #eee;
  padding-top: 90px;
  font-family: 'Roboto', Arial, Helvetica, Sans-serif;
  overflow-x: hidden;
}

.navigation {
  top: 0;
  left: 0;
  padding: 0 10%;
  width: 100%;
  position: fixed;
  color: #fff;
  box-sizing: border-box;
  background: #363636;
  text-align: center;
}

.navigation a {
  color: inherit;
  margin: 35px 5px;
  line-height: 150%;
  padding: 0 5px 0 20px;
  display: inline-block;
  text-decoration: none;
  border-left: 1px solid #fff;
}

.navigation a.active {
  color: yellow;
}

.navigation a:first-child {
  border: 0;
}

.box {
  width: 100vw;
  height: 100vh;
  font-size: 14vw;
  padding-top: 100px;
  text-align: center;
  background: #4CD2DA;
}

.box:nth-child(2) {
  background: #59DAE2;
}

.box:nth-child(3) {
  background: #4372A6;
}

.box:nth-child(4) {
  background: #D8E0E3;
}

.box:nth-child(5) {
  background: #4B565A;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<nav class="navigation">
  <a class="active" href="#about" title="About">About</a>
  <a href="#work" title="Work">Work</a>
  <a href="#clients" title="Clients">Clients</a>
  <a href="#blogs" title="Blogs">Blogs</a>
  <a href="#contact" title="Contact">Contact</a>
</nav>

<div id="container">
  <div id="about" class="box">
    About
  </div>
  
  <div id="work" class="box">
    Work
  </div>
  
  <div id="clients" class="box">
    Clients
  </div>
  
  <div id="blogs" class="box">
    Blogs
  </div>
  
  <div id="contact" class="box">
    Contact
  </div>
</div>

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 come it is not possible for me to choose all elements containing an attribute value saved in a variable?

Imagine you have the following snippet of HTML code: <div data-id=5>...</div> <img data-id=5 src=...> <input data-id=5 ...> ... Your task is to select and remove all elements with the attribute data-id set to 5. Here is one attemp ...

Challenges in displaying a preview of the cart following a successful ajax request

I'm trying to display a cart preview when hovering over a specific shopbag div. To achieve this, I've created another div called livebag where I run a query to fetch and preview the cart items stored in the database. Initially, the livebag div is ...

Trigger an event click once a bootstrap table has been successfully reloaded

In my function, I have an AJAX call and in the success function, I refresh the Bootstrap table. After the refresh, there is a trigger command that I want to execute only when the refresh is completed. How can I achieve that? success: function (result) { c ...

The dropdown menu is obscured by the toolbar

When using ionic4/angular, I want a dropdown menu to display upon clicking on the ion-avatar. However, the dropdown menu is hiding in the toolbar. I have tried setting z-index but it did not work. Any suggestions would be appreciated. You can find the sta ...

Enhanced Search and Replace Techniques in HTML using jQuery and JavaScript

Although I have some experience with jQuery and Javascript, I am by no means an expert. I have been struggling to find a way to achieve my goal using minimal resources. Maybe you can assist me: This is what I am trying to accomplish: I would like to use ...

Adjust the vertical size of the slider in Jssor

Hi there! I'm currently working on a slider that I want to have a dynamic width (100% of the container) and a static height of 550px on PCs, while being responsive on mobile devices. Below is my code snippet: <div class="col-md-6 right-col" id="sl ...

Using AngularJS to create interactive popups within leaflet maps

My map uses leafletjs to create markers such as ev124, ev125, and so on. In addition, there are links with a key attribute like <a ng-click="popup(evsi)" key="124">link</a> Using angular, I extract the key value this way: $scope.popup= funct ...

What is the best way to position a title at the bottom center of each image within my grid gallery?

I'm struggling to find a way to position a title at the bottom of each image in my grid gallery, right in the center of the photo with a light-gray background. I want the text to be fully visible regardless of the image used. Currently, I can only put ...

How to stop event propagation from a draggable element nested within a sortable container in jQuery UI

Here is a link to the code snippet: http://jsfiddle.net/Aa7TW/ {greedy: true} The issue arises with the interaction between droppable and sortable elements. Sortable is triggered when an item is dropped directly onto it, while dropping an item from the ...

Breaking HTML attribute values into separate lines will make the code more organized and easier

Is it possible to format HTML attribute values so they can span across multiple lines? Essentially, I'm wondering if there is a way to include line breaks within a regular typed HTML attribute value. For instance, in the functional code snippet below ...

Passing checkbox values to PHP using Ajax is resulting in a null response

In my attempt to transfer the data from 7 jQuery checkboxes to PHP via Ajax, I have been struggling to populate an array with the values and serialize it before sending it through Ajax. The end goal is to use these checkbox values as conditions in a MySQL ...

Creating tabbed content with a classless CSS design by utilizing radio buttons instead of the traditional unordered

I am attempting to transform the classless CSS and HTML provided below from a list format to using radio buttons and labels for tabbed content. My goal is to make it concise and avoid redundancy. Here is the setup of what I am aiming for: <nav> ...

Clicking a button on every row triggers an update to the data

As a beginner programmer, I am facing a challenge in selecting and updating data when clicking a button on each row. Currently, I am able to select and display data, but only the first update button is functioning. I suspect the issue lies in having the sa ...

Each loop in the forEach function triggers the mouseup event

I am currently utilizing a foreach loop: objects.forEach(function(object) { var button = '<tr><td>' + object.object.code + '</td><td>' + formatDistance(1456000) + &apos ...

Retrieve Header information when making a cross-domain AJAX request

I've been working on a way to validate image URLs by using an AJAX call to check if the image is still available. The challenge I'm facing is that the image server is on a different domain, so I included the crossDomain: true attribute in my AJAX ...

The ASP.NET MVC3 form collection registers as 0 when performing a jQuery ajax post

I'm currently developing a project on ASP.NET MVC3. My current challenge involves POSTing to a method that should return a set of data using the jQuery.ajax api. However, upon handling the request on the server, I noticed that the form collection&apo ...

Upon clicking a button, I aim to retrieve the data from the rows that the user has checked. I am currently unsure of how to iterate through the rows in my mat-table

My goal is to iterate through the column of my mat-table to identify the rows that have been checked, and then store the data of those rows in an array. <td mat-cell *matCellDef="let row"> <mat-checkbox (click)="$event.stopPropagation()" (c ...

The components are not anchored to the window

In the header, I require: The logo to be positioned on the left side of the banner (without space) Both the banner and logo to always be centered on the page regardless of screen size Four images that should always be at the top right corner of the windo ...

Repair the voting system

In my Ruby on Rails app, I have successfully set up an up/down voting system that utilizes ajax. When a user clicks the buttons, it triggers the create method to insert a vote into the database and calculate the total sum of votes. Currently, users can fr ...

Load HighCharts dynamically in a sequential manner

Currently, I am working on dynamically loading a variety of series based on user-selected projects. My tech stack includes Laravel 5.2, PHP 5.6, and HighCharts. I've successfully loaded one JSON file generated upon project selection. However, I aim to ...