-
Star
(189)
You must be signed in to star a gist -
Fork
(34)
You must be signed in to fork a gist
-
-
Save jjmu15/8646226 to your computer and use it in GitHub Desktop.
// Determine if an element is in the visible viewport | |
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) | |
); | |
} | |
The above function could be used by adding a “scroll” event listener to the window and then calling isInViewport(). |
Thx
Nice, be sure to account for anchored elements/z-indices if you're copy pasting this
Thank you!
The drawback is that the whole element with its hight should be in viewport, not just some part of it.
@englishextra: what if the element's height is longer than the viewport?
@bresson make you browser window smaller in height and you target is an image that wil appear only part of it, the isInViewport will not trigger. But it will if the element is not hidden but has no height, say:
somewhere lower in your document:
<div id="disqus_thread"></div> // it has no dynamic children appended yet
if (verge.inViewport(disqus_thread) // false
if (isInViewport(disqus_thread) // true
So the right name would be fitsIntoViewport
I recommend verge
js lib which is small. But for now it wont say if something is in viewport if they are hidded with display none
Works great- thanks!
Thanks, it works perfectly.
thanks so much!
Thanks for this!
Just wrote a similar version that only accounts for height, but returns true when any part of the element is in the viewport:
function isVisible (ele) {
const { top, bottom } = ele.getBoundingClientRect();
const vHeight = (window.innerHeight || document.documentElement.clientHeight);
return (
(top > 0 || bottom > 0) &&
top < vHeight
);
}
thank you Jjmu15 and Tsimons. Your snippets each address different needs.
Just wrote a similar version that only accounts for height, but returns true when any part of the element is in the viewport:
function isVisible (ele) { const { top, bottom } = ele.getBoundingClientRect(); const vHeight = (window.innerHeight || document.documentElement.clientHeight); return ( (top > 0 || bottom > 0) && top < vHeight ); }
this is the one working as of now
Great work guys @jjmu15 and Tsimons@ Your snippets are amazing. I have been looking for something like this. Didn't want to import a library to solve just one problem
you are probably the greatest human being in my perspective now, thanks
Thanks for sharing this inspiring piece of code. ;)
Here is an extended version that supports checking for full visibility in more specific areas.
function isInViewport(element, parentElement=null)
{
var childRect = element.getBoundingClientRect();
if (parentElement == null)
{
// check for full visibility in window area
// (original version)
var html = document.documentElement;
return (
childRect.top >= 0 &&
childRect.left >= 0 &&
childRect.bottom <= (window.innerHeight || html.clientHeight) &&
childRect.right <= (window.innerWidth || html.clientWidth)
);
}
else
{
// check for full visibility in a specific parent element's area
// (for scrollable containers that don't fill the whole window)
var parentRect = parentElement.getBoundingClientRect();
return (
childRect.top >= parentRect.top &&
childRect.left >= parentRect.left &&
childRect.bottom <= parentRect.bottom &&
childRect.right <= parentRect.right
);
}
}
why arent you guys using the
IntersectionObserver API in vanilla JS?
More about it here < https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API >
The event listener on scroll will execute a function many timer as a user scrolls about while the element is in the viewport - madness with a slideshow! Also it takes at least 2 scroll events for element reach the viewport fully.
Need to hit the function only once...
let timerOn = false;
function isInViewport() {
const ele = document.querySelector(".carousel");
const rect = ele.getBoundingClientRect();
if (rect.top >= 0 && rect.bottom <= window.innerHeight && rect.left >= 0 && rect.right <= window.innerWidth) {
if (!timerOn) timer();
}
};
function timer() {
timerId = setInterval("plusSlides(1)", 3000);
timerOn = true;
}
window.addEventListener('scroll', function (event) {
isInViewport();
}) ;
I spent 4 hours looking for a solution to this problem. Thank you!