0

Before anything, let me know if i'm not being clear or if there is a better title. I'm really not good with english, so... excuse me! :)

What i'm trying to do (in part I really don't know how to search for it!) is trying to know when a user is looking at a specific page section, delimited by a anchor element.

<a id="section"></a>

Lets say I have that anchor at some point, and the user may scroll there. Is there any way to know that the user has arrived to that section? I could not find an event for that. Looks like a very trivial task. Something like document.getElementById('section').addEventListener('seen', ...)

Also, if there is any CSS selector (like :hover) to apply some styling when the anchor is met, would be great to know.

I hope i'm being clear! Any hint will be really appreciated.

EDIT: Forgot to say that my current approach will be something like detecing the colission between a fixed nav var and the anchor element, and trigger some action when this happens. EDIT: Didn't work. Position of fixed element really does not change heh...

Emilio Grisolía
  • 1,092
  • 1
  • 9
  • 13
  • 1
    https://stackoverflow.com/questions/123999/how-can-i-tell-if-a-dom-element-is-visible-in-the-current-viewport – john Smith Jun 14 '20 at 22:32

2 Answers2

0

I have provided a sample code that might achieve what you are looking for: the whole idea here is to catch that your anchor element is shown in the screen using isElemSeen function and then the action that is required to be preformed can be applied in actionBasedOnAppearance function, the if closure will handle when when the element appear on the screen while the else closure will handle when the element disappear.

In the provided example the div with id main-container will be colored with green color when the element is appeared on the screen otherwise will be colored with red color.

function isElemSeen (elem) {
  return elem && typeof elem.getBoundingClientRect === 'function'
     && elem.getBoundingClientRect()['bottom'] + window.scrollY <= window.innerHeight
     + window.scrollY && elem.getBoundingClientRect()['top'] + window.scrollY <= window.innerHeight
     + window.scrollY
 }

 function actionBasedOnAppearance() {
     if(isElemSeen(document.getElementById('section'))) {
         document.getElementById('main-container').style.backgroundColor = 'green';
        console.log('I am visible');
     } else {
        document.getElementById('main-container').style.backgroundColor = 'red';
        console.log('I am invisible');
     }
 }

 // This is to catch the event once the page is loaded
 actionBasedOnAppearance();

 // This is to catch the event while you are scrolling 
 window.addEventListener('scroll', function(e) {
     actionBasedOnAppearance();
 });
<h1>Test Scroll Event</h1>
<div id="main-container" style="background-color: blue; width: 1000px; height: 1000px;">
</div>
<a id="section" href="">Hello World</a>

reference: How to Check if element is visible after scrolling?

Karim
  • 178
  • 1
  • 10
0

You can use the IntersectionObserver API to listen for when a user hits a particular page section or even an anchor tag for that matter. Instead of adding scroll listeners or configuring offsets and all the shebang, I feel like using IntersectionObservers is way cleaner and easier.

The Intersection observer constructor takes two arguments, a callback and an options object. You can read up about the options in the documentation. The callback function is where most of your logic on how you'll deal with the entries will reside.

// Define a new observer
const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry > {
       if (entry.isIntersecting) {
           entry.target.classList.add('customStyleClass') // Add a style class that adds color and so on
       } else {
           entry.classList.remove('customStyleClass')
       }
    });
}, {});

const target = document.querySelector('#section');
observer.observe(target);

There's lots of ways to play around with this, I suggest you read the documentation or scour some youtube videos.

MDN Documentation

spaceSentinel
  • 559
  • 4
  • 8