Tips for highlighting the sticky subnav menu option as you scroll

Currently utilizing intersection observer to toggle the visibility of the sticky navbar and make the scroll bar sticky. I am now looking to add a feature where the sub nav options highlight with color as we scroll, focusing on the container with a specific ID near the sticky navbar.

I have attempted various methods but have not been able to achieve the desired outcome.

Below is what I have tried:

<template>
  <div>
    <div id="sticky-nav" class="sticky-nav">
      <a>menu1</a>
      <a>menu2</a>
      <a>menu3</a>
    </div>
    <div id="content" class="content">
      <div class="content-div" id="div1">Div 1</div>
      <div class="content-div" id="div2">Div 2</div>      
    </div>
  </div>
</template>

<script>
export default {
  mounted() {
    const options = {
      root: null, 
      threshold: 0.5,
    };

    const observer = new IntersectionObserver(
      this.handleIntersection,
      options
    );
    observer.observe(document.getElementById('content'));
  },
  methods: {
    handleIntersection(entries) {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          const stickyNavHeight = document.getElementById('sticky-nav').clientHeight;
          const div1Top = document.getElementById('div1').offsetTop - stickyNavHeight;
          const div2Top = document.getElementById('div2').offsetTop - stickyNavHeight;
          
          console.log('Position of Div 1:', div1Top);
          console.log('Position of Div 2:', div2Top);
        }
      });
    },
  },
};
</script>

<style scoped>
.sticky-nav {
  
}

.content {
  
}

.content-div {
  
}
</style>

Expected Solution: Looking for a way to determine the closest div (div1, div2, etc.) to the element with the ID "sticky-nav" when scrolling. Open to any alternative approaches as well.

Answer №1

give this a shot.

<template>
  <div>
    <div class="sticky-nav">
      <a :class="{ active: activeSection === 'div1' }" @click="scrollToSection('div1')">Menu 1</a>
      <a :class="{ active: activeSection === 'div2' }" @click="scrollToSection('div2')">Menu 2</a>
    </div>
    <div class="content">
      <div class="content-div" id="div1">Div 1</div>
      <div class="content-div" id="div2">Div 2</div>  
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      activeSection: null
    };
  },
  mounted() {
    window.addEventListener('scroll', this.handleScroll);
  },
  beforeDestroy() {
    window.removeEventListener('scroll', this.handleScroll);
  },
  methods: {
    handleScroll() {
      const stickyNavHeight = document.querySelector('.sticky-nav').clientHeight;
      const div1Top = document.getElementById('div1').offsetTop - stickyNavHeight;
      const div2Top = document.getElementById('div2').offsetTop - stickyNavHeight;
      const scrollPosition = window.scrollY;
      
      if (scrollPosition >= div1Top && scrollPosition < div2Top) {
        this.activeSection = 'div1';
      } else if (scrollPosition >= div2Top) {
        this.activeSection = 'div2';
      } else {
        this.activeSection = null;
      }
    },
    scrollToSection(sectionId) {
      const sectionTop = document.getElementById(sectionId).offsetTop;
      const stickyNavHeight = document.querySelector('.sticky-nav').clientHeight;
      window.scrollTo({
        top: sectionTop - stickyNavHeight,
        behavior: 'smooth'
      });
    }
  }
};
</script>

<style scoped>
.sticky-nav {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  background-color: #f8f8f8;
  padding: 10px 0;
  z-index: 1000;
}
.sticky-nav a {
  margin: 0 10px;
  text-decoration: none;
  color: #333;
}
.sticky-nav a.active {
  font-weight: bold;
  color: #ff0000;
}
.content {
  padding-top: 50px;
}
.content-div {
  height: 500px;
  border: 1px solid #ccc;
  margin-bottom: 20px;
}
</style>

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 to implement dynamic aggregate functions with parameters in Express and Mongoose

I have implemented an aggregate function in mongoose to fetch some data, with a static implementation. app.get("/male",function (req,res) { Record.aggregate([ { $match: {"gender": "male"} }, { $group:{ _i ...

Incorporating search suggestions into a div with vue 3 and boostrap: a step-by

I am currently experimenting with building a compact search box that offers suggestions using the vue 3 boostrap library. I am aiming to have the suggestions box float on top of the following div without pushing it down. Despite trying to manipulate the z- ...

The presence of inline display causes gaps of white space

Located at the bottom of this webpage is a media gallery. The initial three images comprise the photo gallery, followed by video thumbnails inlined afterwards. However, there seems to be an issue with the alignment of each element within the video gallery. ...

The CSS display:block property isn't functioning as intended

I'm currently working on a contact form using CSS and HTML, but I'm having trouble getting the boxes to display properly in a 'block' form (display:block). HTML: <section class="body"> <form method="post" action="index.php ...

Unable to adjust the main-container height in Bootstrap to 100%

I'm struggling to set the height of my .main-container to 100%. When I try to do that, the height ends up being too high. Here is a screenshot for reference: enter image description here .main-container { height: 94vh; } Here is some of my code ...

What is the best way to add a value to the value attribute of a div using JavaScript?

Is there a way to insert a value into the value attribute of a div using Internet Explorer 9? I have attempted various JavaScript functions, but so far I can only modify the content inside the div and not the value attribute itself. <div id="mydiv" val ...

Is it possible to update the URL dynamically in a Next.js application without relying on the <Link> component?

I'm looking for a way to dynamically change the URL on a page without using <Link>. Specifically, I want to switch to a different URL when a variable changes from false to true, regardless of user interaction. Currently, I'm achieving this ...

The Electronjs application encountered an error while loading with the message "ReferenceError: require is not defined."

Having trouble with an electron application as I encounter an error when running npm start: $ npm start > <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="483c2d3b3c087966786678">[email protected]</a> start C:& ...

Offering fields for modules, main, and browser that meet the needs of ESM, CommonJS, and bundlers

I have upgraded a number of my published npm packages to include both commonjs and esm builds. Some of these packages are meant for use in both node and the browser, and they are all compiled using webpack or rollup. Additionally, all of them are written i ...

What is the best way to loop through an object while keeping track of its value types

I have a JSON file containing UI adjustments sourced from the API: interface UIAdjustmentsJSON { logoSize: number; themeColor: string; isFullScreen: boolean; } To simplify things, let's utilize a static object: const adjustments: UIAdjust ...

Excessive whitespace appearing on the right side of a Wordpress website

Currently, I am working on a project with a WordPress website that is using the TwentyFourteen theme. As I was going through the site, I noticed an unexpected white margin on the right side of the page extending about 200px in width. Upon inspecting it fu ...

Click X button to toggle and close the dropdown menu

After successfully creating a responsive menu that toggles with a hamburger icon at 1205px resolution, I encountered an issue. Once the hamburger icon is clicked and the dropdown menu opens, there seems to be no way to close it. I am looking to add an X bu ...

Issue with Next.js: Callback function not being executed upon form submission

Within my Next.js module, I have a form that is coded in the following manner: <form onSubmit = {() => { async() => await requestCertificate(id) .then(async resp => await resp.json()) .then(data => console.log(data)) .catch(err => console ...

The styled-components in CSS are causing some issues with the color themes

Link to Image Showing the Issue. I have implemented themes and colors in my React application successfully, but I am encountering a peculiar problem with the labels. Whenever I switch the theme from green to blue and then back to green, focusing on the inp ...

Maintain the button's color when clicked UNTIL it is clicked again

I am facing a challenge where I need to dynamically select multiple buttons that change color upon click. Once a button is clicked, it should change color and if clicked again, revert back to its original color. Unfortunately, I cannot rely on HTML attribu ...

Clicking yields no results

let link = '<a href="javascript:void(0);" (click)="redirectToPage(store)" class="btn grey">' + displayText + '</a>'; Upon clicking the button on the page, nothing seems to be happening. Can you help me figure out what I&apo ...

The overlay lingers on the page even after the modal successfully redirects to the search

My goal is to implement a modal that prompts users to input their search term and find recipes with a specific ingredient. I have successfully achieved this by using simple redirection. However, upon redirecting to the search results, the overlay remains o ...

Retrieve data from external URL using API

I am encountering a captchas page when attempting to retrieve JSON data from a URL through my API. Even though I am trying to access an array of JSON data containing openPrice, highPrice, price, and lowPrice, all I seem to get is a captcha form instead of ...

What is the best way to organize a flatlist for rendering?

I'm struggling with separating some flat-lists into different components. How can I arrange the rendering of the flat-list like the sample form (Picture "Sample UI")? I've tried, but it's not working correctly as it renders flat list A first ...

seize the cursor on chrome for windows

I'm experiencing an issue with two cursors appearing in Windows Chrome version 31.0.1650.57. The two cursors are grab and a default arrow. I have applied the following CSS: CSS div { width:200px; height:200px; background-color:maroon; ...