How do I activate a link and smoothly scroll to a designated section on the same page in Next.js by utilizing an ID when it is clicked?

I need help setting up a feature in Next.js that allows for:

Upon clicking a link, the page scrolls to a specific section on the same page. The clicked link becomes visually active (changing color, adding underline, etc.) once scrolled to the corresponding section. This scrolling action is facilitated using an ID within the href attribute of the link.

Here is a snippet of my code:

<ul className = "font-medium flex flex-col p-4 md:p-0 mt-4  md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 transition-all" > {
    navLinks.map((link, index) => {
      return ( 
     <li key = {index} >
        <Link href = {`#${link.path}`}
        scroll className = {cn("block py-2 px-3 text-white  rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white hover:dark:text-blue-500 transition-all")}
        aria-current = "page" >
        {
          link.name
        } 
        </Link> 
      </li>
      );
    })
  } </ul>

Desired Outcome:

When a user clicks on a link with an href containing an ID (e.g., #section1), the page should smoothly scroll to the corresponding element with that ID. The clicked link should visually indicate its active state through CSS styling changes or the addition of a new class.

Answer №1

Here's a method to accomplish this task

import { useState, useEffect } from 'react';
import Link from 'next/link';
import cn from 'classnames'; // Conditionally applying class names

const Navigation = ({ navigationLinks }) => {
  const [activeLink, setActiveLink] = useState(null);

  useEffect(() => {
    const handleScroll = () => {
      const scrollPosition = window.scrollY;
      navigationLinks.forEach((link) => {
        const section = document.getElementById(link.path);
        if (section && scrollPosition >= section.offsetTop - 80 && scrollPosition < section.offsetTop + section.offsetHeight) {
          setActiveLink(link.path);
        }
      });
    };

    window.addEventListener('scroll', handleScroll);
    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, [navigationLinks]);

  return (
    <ul className="font-medium flex flex-col p-4 md:p-0 mt-4 md:flex-row md:space-x-8 rtl:space-x-reverse md:mt-0 transition-all">
      {navigationLinks.map((link, index) => (
        <li key={index}>
          <Link href={`#${link.path}`} scroll={false}>
            <a
              className={cn(
                "block py-2 px-3 text-white rounded md:bg-transparent md:text-blue-700 md:p-0 dark:text-white transition-all",
                activeLink === link.path && "underline text-blue-500" 
              )}
              aria-current={activeLink === link.path ? "page" : undefined}
            >
              {link.name}
            </a>
          </Link>
        </li>
      ))}
    </ul>
  );
};

export default Navigation;

Ensure the scrolling behavior in specific sections by adding an id attribute in those areas

<div id="section1" className="section">
  <h1>Section 1</h1>
  <p>Content for Section 1</p>
</div>

<div id="section2" className="section">
  <h1>Section 2</h1>
  <p>Content for Section 2</p>
</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

Removing an object from an array within a document based on its index is a simple process

I have a specific data entry stored in my MongoDB Atlas database: { _id: new ObjectId("62bf2315503e821576e53c53"), foodName: 'food name', foodPrice: '17', category: 'sweets', foodDesc: 'this is so ...

Is there a method to retrieve user information from the Stripe API using getServerSideProps in Next.JS?

I'm currently facing a challenge in retrieving user data from Stripe within the getServerSideProps function in Next.JS. My goal is to pass this data down to other components, but I'm struggling to extract it from the getServerSideProps function. ...

Choosing the Offspring: Deliberating on Multiple Children with Identical Names in Selenium

Just starting out with Selenium and web development in general, I've encountered a problem with locating an element using XPath. selenium.common.exceptions.NoSuchElementException I've been trying to troubleshoot for a while now, but haven' ...

Identifying collisions or contact between HTML elements with Angular 4

I've encountered an issue that I could use some help with. I am implementing CSS animations to move p elements horizontally inside a div at varying speeds. My goal is for them to change direction once they come into contact with each other. Any sugges ...

Tips for integrating AngularJS/Material1 with Angular/Material2 in a hybrid application

Currently, we are in the process of migrating an AngularJS + angular materialv1 app to Angular + angular materialv2. The application is currently running in hybrid mode, and everything is functioning well except for some CSS styling issues. We have encoun ...

Utilizing NextJS to fetch JSON data from the public directory

I am having trouble importing a globe.json file from my public folder. When I try to import it, I get the error message Module not found: Can't resolve '/globe.json' This is how my files are structured currently: public globe.json src ...

Using the CSS trick of First-of-type and Last-of-type can result in shortened rounded edges when viewed in IE11

When using the radio+label trick to style radio buttons, a peculiar issue arises in Internet Explorer 11 (IE11). The first and last buttons in each set appear to have their bottom parts cut off or shortened, depending on the background displayed. Removing ...

How to Modify Footer Height in MUI Datagrid Version 5

I've been searching high and low for a way to adjust the footer height on a DataGrid without success. I thought there might be a straightforward solution like headerHeight, but it appears not to be available. Am I going crazy or simply overlooking som ...

Updating backgroundPosition for dual background images within an HTML element using Javascript

Issue at Hand: I am currently facing a challenge with two background images positioned on the body tag; one floating left and the other right. The image on the left has a padding of 50px on the left side, while the image on the right has a padding of 50px ...

Captivating Images accompanied by Descriptive Captions

I was wondering if there is a straightforward method using only CSS and HTML to address this particular issue. I am in the process of creating a marquee that displays images within a fixed-width div. The number of images exceeds the capacity of the div, ...

What is the best way to address caching fonts and files within CSS?

Utilizing the font icon for displaying icons may result in difficulty when adding new icons to the font due to caching issues. Clearing the cache is often necessary to refresh the display. How can I address this concern? ...

Ways to show text on top of an image using CSS

Seeking help! I'm attempting to overlay some text on top of an image, here's the link: http://jsfiddle.net/5AUMA/31/ The challenge is aligning this text to the bottom part of the image. I've tried using this CSS: .head_img p { position ...

Blending the power of google-maps-react with the versatility of react-router

While working on my project, I encountered an issue with google-maps-react. It seems that when I try to include a <Link /> from react-router-dom alongside multiple <Marker />, there is a conflict. This is the structure of my code: render() { ...

Trim the data in the following table cell using CSS

I'm trying to create a list using a table structure: https://i.sstatic.net/ucICV.png However, the lengthy URL is causing the table to expand wider than desired. I have attempted solutions like: table { table-layout: fixed; width: 100%; } and td.t ...

Synchronize numerous devices seamlessly using React Native without an internet connection

I'm facing an issue where multiple Android devices are connected to the same WiFi network but there is no internet connection. I need to sync data between these devices without requiring internet access. Is it possible to synchronize data on a local n ...

Should one consider using Eval?

I encountered a scenario where I needed to dynamically retrieve the object value from an array that contained object keys retrieved from an API. I opted for a solution that involved using the eval function. class App extends React.Component { constru ...

Capturing deprecated Material UI alerts

At our company, we have a central shared material UI theme that different teams incorporate into their codebases. Although we make an effort to keep up with the latest versions, sometimes the central repository lags behind when there are significant chang ...

Padding centered on a responsive one-page website

As I work on creating a onesie scrolling website, I've run into an issue. I'm trying to center my text on the first "page," but I can't seem to get it to look good on both phones and desktops simultaneously. Using padding-top: 50% makes it l ...

Using AngularJS to Retrieve a Specific DOM Element Using its Unique Identifier

Example Please take a look at this Plunkr example. Requirement I am looking for a way to retrieve an element by its id. The provided code should be capable of applying a CSS class to any existing DOM element within the current view. This functionality ...

Is there a way I can appropriately display an image in a specific size box?

Check out the code snippet I wrote below: import React from 'react' function OurCourse() { return ( <div className='w-full '> <div className='w-full h-[390px]' style={{ backgroundImage:&apos ...