I'm making a nextjs app , I want to change the navbar active button according the the visible sections in the viewport the page children look like this
<div id="section1" > </div>
<div id="section2" > </div>
...
<div id="faq" > </div>
<div id="contact" > </div>
for example when the user scrolls and the current div in the screen is the contact form
I set it the route to /#contact
My main problem is how to detect the current viewable element in the viewport
How can I achieve this ?
CodePudding user response:
Javascript:
// simple function to use for callback in the intersection observer
const changeNav = (entries, observer) => {
entries.forEach((entry) => {
// verify the element is intersecting
if(entry.isIntersecting && entry.intersectionRatio >= 0.55) {
// remove old active class
document.querySelector('.active').classList.remove('active');
// get id of the intersecting section
var id = entry.target.getAttribute('id');
// find matching link & add appropriate class
var newLink = document.querySelector(`[href="#${id}"]`).classList.add('active');
}
});
}
// init the observer
const options = {
threshold: 0.55
}
const observer = new IntersectionObserver(changeNav, options);
// target the elements to be observed
const sections = document.querySelectorAll('section');
sections.forEach((section) => {
observer.observe(section);
});
HTML:
nav
ul
li
a(href='#one').active One
li
a(href='#two') Two
li
a(href='#three') Three
li
a(href='#four') Four
li
a(href='#five') Five
section#one
p Slide One
section#two
p Slide Two
section#three
p Slide Three
section#four
p Slide Four
section#five
p Slide Five
CSS:
nav
position fixed
width 100%
top 0
left 0
right 0
background-color white
ul
list-style-type none
display flex
align-items center
justify-content space-around
width 100%
max-width 800px
height 50px
margin 0 auto
padding 0
li
display inline-block
padding 5px
a
display block
height 40px
padding 0 20px
line-height 40px
text-decoration none
text-transform uppercase
color #323232
font-weight bold
border-radius 4px
transition background-color 0.3s ease-in
&:hover
&:active
&:focus
background-color rgba(#B8D6A8, 0.5)
&.active
background-color rgba(#B8D6A8, 0.5)
section
display flex
align-items center
justify-content center
min-height 100vh
p
text-align center
color white
font-size 3.5em
font-weight bold
text-transform uppercase
#one
background-color #6CA392
#two
background-color #FFA58C
#three
background-color #FF4F30
#four
background-color #576B51
#five
background-color #392A1B