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:
What you want:
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.