Vignesh T.V.
Vignesh T.V.

Reputation: 1860

Check if an element is visible on screen

I am using this plugin - isOnScreen to check whether an element is visible on the viewport (to check if posts has been viewed or not).

But is it possible to have a callback of some sort so that instead of having a setTimeOut and checking the visibility of each and every post every time, fire a callback when the respective element is visible?

Or is there any other library I can use to do this?

I am talking about the visual viewport. (Not css visibility)

Upvotes: 5

Views: 14760

Answers (3)

Manish Thomas
Manish Thomas

Reputation: 199

There are mainly two ways to check if an element is visible/hidden on the screen during scrolling:

  1. Listening to the window scroll event.
  2. Observing the element for visibility using Intersection Observer API.

Scroll events have a lot of performance issues.

The new way is using Intersection Observer API. Intersection Observer API makes it possible to know when an element enters or exits the browser viewport. This API is asynchronous

var observer = new IntersectionObserver(function(entries) {
    if(entries[0].isIntersecting === true)
        console.log('Element is fully visible in screen');
}, { threshold: [1] });

observer.observe(document.querySelector("#element"));

Threshold is a number between 0 and 1, that represents the viewable area of the target element in the screen. For example, 0 represents no area of element is visible. A value of 0.10 represents about 10% area is viewable in the screen. Value of 1 means element is fully viewable in the screen.

Upvotes: 5

Darlesson
Darlesson

Reputation: 6162

I recently worked on a small library that checks when an element is on the viewport called viewport-action. It could be handy for cases like yours.

Feel details to consider:

  • You can have the callback called once or every time.
  • You can check how much of the element is shown by checking when a certain height, width or area is shown.
  • It waits for the DOMContentLoaded event in browsers or deviceready in Cordova apps before starting checking for elements (in case it's a Cordova app).
  • It doesn't depend on Promise (yet) to support applications without it and older browsers.

See the example below where it checks for how much of the element is shown based on percentage.

var options = {
    once: true
};

viewportAction.add('#check', function (e) {
 
    var percentageShown = (e.detail.availableArea / (e.detail.width * e.detail.height)) * 100;
 
    // Load an image inside the element when the area visible is bigger
    // than 60% of its area.
    if (percentageShown > 60) {
 
        e.target.innerText = 'Showing ' + percentageShown.toFixed(0) + '% of the element';
 
        // Remove handler if you don't want to use options
        // e.removeHandler();
    } else {
      e.target.innerText = 'Showing less than 60%';
    }
    
// Use options, optionally
//}, options);
});
#check {
  background-color: #F00;
  color: #FFF;
  height:500px;
  width; 100%;
}

.spacer {
  background-color: #CCC;
  height: 300px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/viewportAction.min.js"></script>

<div class="spacer">Scroll down or up</div>

<div id="check"></div>

<div class="spacer"></div>

Upvotes: 0

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276266

Here is a script returning a promise using the new IntersectionObserver API for checking whether or not an element is actually visible in the viewport:

function isVisible(domElement) {
  return new Promise(resolve => {
    const o = new IntersectionObserver(([entry]) => {
      resolve(entry.intersectionRatio === 1);
      o.disconnect();
    });
    o.observe(domElement);
  });
}

Which you can use in your code:

const visible = await isVisible(document.querySelector('#myElement'));
console.log(visible);

Upvotes: 21

Related Questions