Reputation: 157
hello there i have a problem. i want to full intersect of selected observing element height. not half or double intersect like below in the picture two elements has been intersected when im scrolling i want only who is full height when i scroll
here is my HTML code
<ul>
<li><a href="#one" class="active">P1</a></li>
<li><a href="#two">P2</a></li>
<li><a href="#three">P3</a></li>
<li><a href="#four">P4</a></li>
</ul>
<div id="one">
<p>P1 </p>
<section>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</section>
</div>
<div id="two">
<p>P2 </p>
<section>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</section>
</div>
<div id="three">
<p>P3 </p>
<section>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</section>
</div>
<div id="four">
<p>P4 </p>
<section>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</section>
</div>
here is my Javascript code
let observer = new IntersectionObserver(beTouching)
document.querySelectorAll('div').forEach(div=>{
observer.observe(div)
})
function beTouching(elements){
elements.forEach(element=>{
if(element.isIntersecting&&element.boundingClientRect.height){
console.log(element.target)
let id = element.target.getAttribute('id')
document.querySelector('ul li a[href*='+id+']').classList.add('active');
}else{
let id = element.target.getAttribute('id')
document.querySelector('ul li a[href*='+id+']').classList.remove('active');
}
})
}
here is my Css code
*{
padding: 0;
margin: 0;
box-sizing: border-box;
text-decoration: none;
scroll-behavior: smooth;
}
body{
}
div#one{
background: cornflowerblue;
height: 100vh;
}
div#two{
background: coral;
height: 100vh;
}
div#three{
background: pink;
height: 100vh;
}
div#four{
background: skyblue;
height: 100vh;
}
.active{
background: red !important;
color: white !important;
padding: 20px;
}
ul{
height: 50px;
width: 100%;
background: green;
display: flex;
list-style-type: none;
justify-content: space-around;
align-items: center;
position: sticky;
top: 0px;
}
Upvotes: 0
Views: 664
Reputation: 4033
From what I understand, you want your Nav links to be highlighted whenever the section they are linked to is visible in the viewport and also, avoiding two Nav links being highlighted at the same time.
You can achieve this with some slight modifications and using the rootMargin
of the intersection observer.
Intersection observer callback:
function beTouching (elements) {
elements.forEach(element=> {
const id = element.target.getAttribute('id')
const menuLink = document.querySelector(`ul li a[href='#${id}']`)
if(element.isIntersecting) {
document.querySelector('ul li a.active').classList.remove('active')
menuLink.classList.add('active')
}
})
}
In your intersection observer definition:
const observer = new IntersectionObserver(beTouching, {
rootMargin: '-50% 0px'
})
Explanation:
Using a negative rootMargin
for top and bottom margins, you're basically "reducing" the intersection section vertically, therefore, avoiding two sections that are both partially visible in the viewport to be intersected at the same time. Now, by doing this without this lines of code:
if(element.isIntersecting) {
document.querySelector('ul li a.active').classList.remove('active')
menuLink.classList.add('active')
}
What would happen is that at some point in the middle when you are scrolling, none of the sections will be intersecting, so no Nav links will be highlighted and this is an undesirable behaviour. So, you put as a condition that only if the element is intersecting, then proceed to remove the active
class from the a
tag corresponding to the section that was previously intersecting and add that active
to the section that is currently intersecting.
Note: You can play around with the negative top and bottom margins to find a combination that works the best for you. If you try different values, make sure the sum of them is always equal to 100% (for example, -30% top, -70% bottom).
Upvotes: 1