简体   繁体   中英

Check if element is partially in viewport

I'm trying to determine if an element is partially or fully in the viewport.

I've found this which will determine if an element is fully in view but kept getting confused when trying to determine partial visibility. I don't want to use jQuery.

Basically, the idea is that there will be an element on the page that could be out of view. Once the user scrolls that element into view, even partially, it should trigger an event. I'll handle the event trigger by binding an onscroll event. I just need the detection to work properly.

function isInViewport(element) {
    var rect = element.getBoundingClientRect();
    var html = document.documentElement;
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || html.clientHeight) &&
        rect.right <= (window.innerWidth || html.clientWidth)
    );
}

Any help would be greatly appreciated!

Late answer, but about a month ago I wrote a function that does exactly that, it determines how much an element is visible measured in percent in the viewport. Ive tested it in chrome, firefox, ie11, ios on iphone/ipad. The function returns true when X percent (as a number from 0 to 100) of the element is visible. Only determines if the measurements of the element are visible and not if the element is hidden with opacity, visibility etc..

const isElementXPercentInViewport = function(el, percentVisible) {
  let
    rect = el.getBoundingClientRect(),
    windowHeight = (window.innerHeight || document.documentElement.clientHeight);

  return !(
    Math.floor(100 - (((rect.top >= 0 ? 0 : rect.top) / +-rect.height) * 100)) < percentVisible ||
    Math.floor(100 - ((rect.bottom - windowHeight) / rect.height) * 100) < percentVisible
  )
};

You need a solution based on element.offsetTop , element.offsetLeft , element.offsetHeight , element.offsetWidth , window.innerWidth and window.innerHeight

(depending on the situation, you might also want to take the scrolling position into consideration)

 function isInViewport(element){ if(element.offsetTop<window.innerHeight && element.offsetTop>-element.offsetHeight && element.offsetLeft>-element.offsetWidth && element.offsetLeft<window.innerWidth){ return true; } else { return false; } } function test(){ alert(isInViewport(document.getElementById("elem"))?"Yes":"No"); }
 #elem{width: 20px; height: 20px; background: red; } #elem{position: absolute;top: -9px;left: 600px;}
 <div id="elem"></div> <button onclick="test()">Check</button>

 function partInViewport(elem) { let x = elem.getBoundingClientRect().left; let y = elem.getBoundingClientRect().top; let ww = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); let hw = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); let w = elem.clientWidth; let h = elem.clientHeight; return ( (y < hw && y + h > 0) && (x < ww && x + w > 0) ); } document.addEventListener("scroll", ()=>{ let el = document.getElementById("test"); if (partInViewport(el)) { document.getElementById("container").style.backgroundColor = "green"; } else { document.getElementById("container").style.backgroundColor = "red"; } });
 #test { height: 200px; width: 145px; background-color: grey; } #container { height: 400px; width: 345px; transform: translate(400px, 360px); background-color: red; display: grid; align-items: center; justify-items: center; } body { height: 1500px; width: 1500px; }
 <div id="container"> <div id="test"></div> </div>

My example for this code: https://jsfiddle.net/xqpebwtv/27/

What your code is saying is that:

  • The top side of the element must be below the top side of the window,
  • The left of the element must be to the right of the left side of the window,
  • The bottom side of the element must be to the top of the bottom side of the window, AND
  • The right side of the element must be to the left of the right side of the window

What you want:

  • The top side of the element must be below the top side of the window OR the bottom side of the element must be above the bottom side of the window, AND
  • The left side of the element must be to the right of the left side of the window OR the right side of the element must be to the left of the right side of the window

Take what you will from that, the code should be simple enough from here.

This should do it, offsets are not needed, since we are comparing client rectangles.

function isPartiallyVisibleInViewport(element, viewport) {
  var bound = element.getBoundingClientRect();
  var bound2 = viewport.getBoundingClientRect();
  return bound.bottom > bound2.top && bound.top < bound2.bottom;
}

This function only checks vertically and must be extended if you also want to check horizontally:

return bound.bottom > bound2.top && bound.top < bound2.bottom && bound.right > bound2.left && bound.left < bound2.right;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM