1

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)

Vidya Sagar
  • 1,677
  • 3
  • 15
  • 27
Vignesh T.V.
  • 1,590
  • 1
  • 24
  • 44
  • No its not a duplicate of the mentioned question. I am talking about the visual viewport (not the css visibility) – Vignesh T.V. Dec 19 '15 at 15:05
  • 1
    I really think this is not a duplicate of that question. This is to check whether or not an element is currently visible in the viewport. – jianweichuah Dec 19 '15 at 15:09
  • 1
    anyway, I think one easy way to do it can be listening to the scroll event and have this check in there. `$(window).scroll(function() { if ($('selector').isOnScreen()) {console.log("element has been seen!")} });` – jianweichuah Dec 19 '15 at 15:13
  • 1
    You can subsribe to scroll and resize events and only check visibility on these events. This only works if your page is more or less static. If elements move around (for example when an element above disappears) this does not work. – lex82 Dec 19 '15 at 15:13
  • @jianweichuah: Thanks. Do sites like Facebook use same way to check whether a post has been viewed or do they do something different? – Vignesh T.V. Dec 19 '15 at 15:37
  • I'm not sure about those sites but I'd suspect this is commonly used. I use it for a chrome extension and it works really well. https://github.com/jianweichuah/miniyoutube – jianweichuah Dec 19 '15 at 15:39
  • Thanks. Nice extension by the way. – Vignesh T.V. Dec 19 '15 at 15:41
  • 1
    @benjamin-gruenbaum, as mentioned above, this is not a duplicated question. This question is related to whether an element is on the viewport. The other is about whether the element is visible. Could you unmark as duplicated? – Darlesson Dec 27 '18 at 06:18
  • 1
    @Darlesson done, I think it's now sufficiently different and this can be neatly answered with intersectionobserver – Benjamin Gruenbaum Dec 27 '18 at 09:18

3 Answers3

5

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);
Benjamin Gruenbaum
  • 246,787
  • 79
  • 474
  • 476
0

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/viewport-action@0.2.0/dist/viewportAction.min.js"></script>

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

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

<div class="spacer"></div>
Darlesson
  • 3,864
  • 2
  • 17
  • 23
0

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.

Manish Thomas
  • 111
  • 1
  • 4