2

I am trying to create a simple landing page with React. As per the title I have tried to get the active section heading (in the navbar) to be highlighted (change color) when the user scrolls to that section on the page, no success so far even after searching online for a long time. Really stuck. Following the tutorial, I am using styled-components for styling, different files for each component. Here is the code for my Navbar:

import React, { useState, useEffect } from 'react'
import styled from 'styled-components'
import { FaBars, FaTimes } from 'react-icons/fa'
import { IconContext } from 'react-icons/lib'
import { Link } from 'gatsby'
import Icon from '../images/Icon.png'
import { ButtonOne } from './Button'
import ScrollSpy from 'react-scrollspy-navigation';
import './layout.css'


const Navbar = () => {
    const [click, setClick] = useState(false)
    const [scroll, setScroll] = useState(false)

    const handleClick = () => setClick(!click)
    
    const changeNav = () => {
        if (window.scrollY >= 130){
            setScroll(true)
        } else {
            setScroll(false)
        }
    }

    useEffect(() => {
        changeNav()
        window.addEventListener('scroll', changeNav)
    }, [])
    
    return (
        <>
            <IconContext.Provider value={{ color: '#fabf49'}}>
                <Nav active={scroll} click={click}>
                    <NavbarContainer>
                        <NavLogo to='/'>
                            <NavIcon>
                                <img src={Icon} height={100} width={100} alt='Icon' />
                            </NavIcon>
                        </NavLogo>
                        <MobileIcon onClick={handleClick}>{click ? <FaTimes /> : <FaBars />}</MobileIcon>
                        <NavMenu onClick={handleClick} click={click}>
                            <ScrollSpy offsetTop={80} duration={1500}>
                                <a href='/#s1' ref={React.createRef()}>
                                    <NavItem>
                                        <NavLinks to='/#s1' activeClassName={`active`}>Company</NavLinks>
                                    </NavItem>
                                </a>
                                <a href='#s4' ref={React.createRef()}>
                                    <NavItem>
                                        <NavLinks to='/#s4' activeClassName={`active`}>Features</NavLinks>
                                    </NavItem>
                                </a>
                                <a href='#s7' ref={React.createRef()}>
                                <NavItem>
                                    <NavLinks to='/#s7' activeClassName={`active`} >Partners</NavLinks>
                                </NavItem>
                                </a>
                                <a href='#s6' ref={React.createRef()}>
                                    <NavItem>
                                        <NavLinks to='/#s6' activeClassName={`active`}>Updates</NavLinks>
                                    </NavItem>
                                </a>
                                <a href='#s8' ref={React.createRef()}>
                                    <NavItem>
                                        <NavLinks to='/#s8' activeClassName={`active`}>Careers</NavLinks>
                                    </NavItem>
                                </a>
                                <a href='#s8' ref={React.createRef()}>
                                    <NavItem>
                                        <NavLinks to='/#s8' activeClassName={`active`}>Contact Us</NavLinks>
                                    </NavItem>
                                </a>
                                <NavBtn>
                                    <ButtonOne a href='#s8' ref={React.createRef()} style={{scrollBehavior: "smooth"}}>BOOK NOW</ButtonOne>
                                </NavBtn>
                            </ScrollSpy>
                        </NavMenu>
                        
                    </NavbarContainer>
                </Nav>
            </IconContext.Provider>            
        </>
    )
}

export default Navbar


const Nav = styled.div`
    background: ${({ active }) => (active ? '#1b2227' : 'transparent')};
    height: 80px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 1rem;
    position: sticky;
    top: 0;
    z-index: 999;


    @media screen and (max-width: 1120px) {
        background: ${({ click }) => (click ? '#1b2227' : 'transparent')};
        transition: 0.8s all ease;
        position: sticky;
        background: ${({ active }) => (active ? '#1b2227' : 'transparent')};
        height: 80px;
        display: flex;
        justify-content: center;
        align-items: center;
        font-size: 1rem;
        position: sticky;
        top: 0;
        z-index: 999;
    }
`
const NavbarContainer = styled.div`
    display: flex;
    justify-content: space-between;
    height: 80px;
    z-index: 1;
    width: 100%;
`
const NavLogo = styled(Link)`
    color: white;
    justify-content: flex-start;
    cursor: pointer;
    text-decoration: none;
    font-size: 1.5rem;
    display: flex;
    align-items: center;
    margin-left: 2.5rem;

`
const NavIcon = styled.div`
    margin: 0 0.5rem 0 2rem;
`

const MobileIcon = styled.div`
    display: none;

    @media screen and (max-width: 1120px) {
        display: block;
        position: absolute;
        top: 0;
        right: 0;
        transform: translate(-100%, 60%);
        font-size: 1.8rem;
        cursor: pointer;
    }
`
const NavMenu = styled.ul`
    display: flex;
    align-items: center;
    list-style: none;
    text-align: center;

    @media screen and (max-width: 1120px) {
        display: flex;
        flex-direction: column;
        width: 100%;
        height: 90vh;
        position: absolute;
        top: ${({ click }) => (click ? '100%' : '-1000px')};
            opacity: 1;
            transition: all 0.2s ease;
            background: #1b2227;
            color: #fabf49;
    }
`

const NavLinks = styled(Link)`
    color: #fff;
    display: flex;
    align-items: center;
    text-decoration: none;
    padding: 0.5rem 1rem;
    height: 100%;
    
    
    &:hover {
        color: #fabf49;
    }

    @media screen and (max-width: 1120px) {
        text-align: center;
        padding: 2rem;
        width: 100%;
        display: table;
        color: #fabf49;


        &:hover {
            color: white;
            transition: all 0.3s ease;
        }
    }
`

const NavItem = styled.li`
    height: 80px;
    margin-right: 2rem;

    @media screen and (max-width: 1120px) {
        width: 100%;
    }
`

const NavBtn = styled.div`
  display: flex;
  align-items: center;
  margin-right: 3rem;

  @media screen and (max-width: 1120px) {
    display: none;
  }

`

and here is my index page where all the different sections are assembled into the landing page:

import * as React from "react"


import Layout from "../components/layout"
import Seo from "../components/seo"
import Hero from "../components/Hero"
import SectionTwo from "../components/SectionTwo"
import SectionThree from "../components/SectionThree"
import SectionFour from "../components/SectionFour"
import SectionFive from "../components/SectionFive"
import SectionSix from "../components/SectionSix"
import Partners from "../components/Partners"



const IndexPage = () => (
  <Layout>
    <Seo title="CARNIVAL" />
    <section id='s1'><Hero /></section>
    <section id='s2'><SectionTwo /></section>
    <section id='s3'><SectionThree /></section>
    <section id='s4'><SectionFour /></section>
    <section id='s5'><SectionFive /></section>
    <section id='s6'><SectionSix /></section>
    <section id='s7'><Partners /></section>        
    
  </Layout>
)

export default IndexPage

For additional info here is the Layout component:

import * as React from "react"
import Footer from "./Footer"
import { GlobaStyle } from "./GlobalStyles"

import Navbar from "./Navbar"


const Layout = ({ children }) => {
  

  return (
    <>
      <GlobaStyle />
      <Navbar />
      
        <main>{children}</main>

        
        <section id='s8'><Footer /></section>  
    </>
  )
}



export default Layout

and the css file (many related answers have a css file so I tried that too):

.active{
    color: #fabf49;
}

I have managed to get the scrollspy working, however I am stuck on the active part being highlighted/custom styled in the navbar.

Ferran Buireu
  • 28,630
  • 6
  • 39
  • 67

0 Answers0