如何判断一个DOM元素在当前视口中是否可见?
有没有一种有效的方法来判断DOM元素(在HTML文档中)是否当前可见(出现在视口中 )?
(关于Firefox的问题)
更新:时间stream逝,所以我们的浏览器。 这种技术不再被推荐 ,如果你不需要支持IE <7,你应该使用@ Dan的解决scheme( https://stackoverflow.com/a/7557433/5628 )。
原始解决scheme(现已过时):
这将检查元素在当前视口中是否完全可见:
function elementInViewport(el) { var top = el.offsetTop; var left = el.offsetLeft; var width = el.offsetWidth; var height = el.offsetHeight; while(el.offsetParent) { el = el.offsetParent; top += el.offsetTop; left += el.offsetLeft; } return ( top >= window.pageYOffset && left >= window.pageXOffset && (top + height) <= (window.pageYOffset + window.innerHeight) && (left + width) <= (window.pageXOffset + window.innerWidth) ); }
您可以简单地修改它以确定元素的任何部分在视口中是否可见:
function elementInViewport2(el) { var top = el.offsetTop; var left = el.offsetLeft; var width = el.offsetWidth; var height = el.offsetHeight; while(el.offsetParent) { el = el.offsetParent; top += el.offsetTop; left += el.offsetLeft; } return ( top < (window.pageYOffset + window.innerHeight) && left < (window.pageXOffset + window.innerWidth) && (top + height) > window.pageYOffset && (left + width) > window.pageXOffset ); }
现在大多数浏览器都支持getBoundingClientRect方法,这已经成为最佳实践。 使用旧的答案是非常缓慢 , 不准确,并有一些错误 。
select正确的解决scheme几乎从不精确 。 你可以阅读更多关于它的错误。
此解决scheme已在IE7 +,iOS5 + Safari,Android2 +,Blackberry,Opera Mobile和IE Mobile 10上进行testing 。
function isElementInViewport (el) { //special bonus for those using jQuery if (typeof jQuery === "function" && el instanceof jQuery) { el = el[0]; } var rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */ rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */ ); }
如何使用:
你可以确定上面给出的函数在被调用的时候返回正确的答案,但是跟踪元素的可见性作为一个事件呢?
将以下代码放在<body>
标记的底部:
function onVisibilityChange(el, callback) { var old_visible; return function () { var visible = isElementInViewport(el); if (visible != old_visible) { old_visible = visible; if (typeof callback == 'function') { callback(); } } } } var handler = onVisibilityChange(el, function() { /* your code go here */ }); //jQuery $(window).on('DOMContentLoaded load resize scroll', handler); /* //non-jQuery if (window.addEventListener) { addEventListener('DOMContentLoaded', handler, false); addEventListener('load', handler, false); addEventListener('scroll', handler, false); addEventListener('resize', handler, false); } else if (window.attachEvent) { attachEvent('onDOMContentLoaded', handler); // IE9+ :( attachEvent('onload', handler); attachEvent('onscroll', handler); attachEvent('onresize', handler); } */
如果你做任何DOM修改,他们当然可以改变你的元素的可见性。
指南和常见的陷阱:
也许你需要跟踪页面缩放/移动设备捏? jQuery应该处理缩放/捏交叉浏览器,否则第一或第二个链接应该帮助你。
如果修改DOM ,则会影响元素的可见性。 你应该控制它并手动调用handler()
。 不幸的是,我们没有跨浏览器的onrepaint
事件。 另一方面,它允许我们进行优化,并仅对DOM修改进行重新检查,这些修改可能会改变元素的可见性。
永远不要在jQuery $(document).ready()里面使用它,因为现在没有保证CSS被应用了。 你的代码可以在你的CSS硬盘本地工作,但是一旦放在远程服务器上就会失败。
在DOMContentLoaded
被激发之后, 样式被应用 ,但是图像尚未加载 。 所以,我们应该添加window.onload
事件监听器。
我们无法捕捉缩放/捏事件。
最后的手段可能是以下代码:
/* TODO: this looks like a very bad code */ setInterval(handler, 600);
如果您关心网页上的选项卡是否处于活动状态并可见,则可以使用非常棒的functionpageVisibiliy HTML5 API。
TODO:这种方法不能处理两种情况:
- 使用
z-index
重叠 -
在元素的容器中使用
overflow-scroll
-
尝试新的东西https://pawelgrzybek.com/the-intersection-observer-api-explained/
Dan提供的答案有一些问题,可能会使其成为某些情况下不适合的方法。 其中一些问题在接近底部的答案中被指出,他的代码会给出下列元素的误报:
- 隐藏在被testing者面前的另一个元素
- 在父母或祖先元素的可见区域之外
- 通过使用CSS
clip
属性隐藏的元素或其子元素
这些限制在以下简单testing结果中得到certificate:
解决scheme: isElementVisible()
下面是这些问题的解决scheme,下面的testing结果和代码的一些部分的解释。
function isElementVisible(el) { var rect = el.getBoundingClientRect(), vWidth = window.innerWidth || doc.documentElement.clientWidth, vHeight = window.innerHeight || doc.documentElement.clientHeight, efp = function (x, y) { return document.elementFromPoint(x, y) }; // Return false if it's not in the viewport if (rect.right < 0 || rect.bottom < 0 || rect.left > vWidth || rect.top > vHeight) return false; // Return true if any of its four corners are visible return ( el.contains(efp(rect.left, rect.top)) || el.contains(efp(rect.right, rect.top)) || el.contains(efp(rect.right, rect.bottom)) || el.contains(efp(rect.left, rect.bottom)) ); }
通过testing: http : //jsfiddle.net/AndyE/cAY8c/
结果是:
补充笔记
然而,这种方法并不是没有其自身的限制。 例如,即使前面的元素实际上并没有隐藏任何部分,在同一位置被testing的元素比在另一元素上具有更低的z索引将被标识为隐藏。 尽pipe如此,这种方法在Dan的解决scheme没有涵盖的某些情况下有其用处。
element.getBoundingClientRect()
和document.elementFromPoint()
都是CSSOM工作草案规范的一部分,并且至less在IE 6及更高版本和大多数桌面浏览器中都支持很长时间(尽pipe并不完美)。 有关这些function的更多信息,请参阅Quirksmode 。
contains()
用于查看document.elementFromPoint()
返回的元素是否是我们要testing可见性的元素的子节点。 如果返回的元素是相同的元素,它也返回true。 这只是使检查更健壮。 它在所有主stream浏览器都支持,Firefox 9.0是最后一个添加它的地方。 对于较早的Firefox支持,请查看此答案的历史logging。
如果你想要在元素周围testing更多的可见性点,也就是说,为了确保元素的覆盖范围不超过50%,那么调整答案的最后部分不会太多。 但是,请注意,如果您检查每个像素以确保其100%可见,则可能会非常慢。
我试了丹的答案, 但用于确定边界的代数是不正确的。 ryanve的答案更接近,但被testing的元素应该在视口内至less有1个像素,所以试试这个函数:
function isElementInViewport(el) { var rect = el.getBoundingClientRect(); return rect.bottom > 0 && rect.right > 0 && rect.left < (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ && rect.top < (window.innerHeight || document.documentElement.clientHeight) /* or $(window).height() */; }
有一个名为inview的 jQuery插件可以完成这项工作
作为公共服务:
丹的答案是正确的计算(元素可以>窗口,特别是在手机屏幕上),正确的jQuerytesting,以及添加isElementPartiallyInViewport:
顺便说一句,window.innerWidth和document.documentElement.clientWidth之间的区别是clientWidth / clientHeight不包括滚动条,而window.innerWidth / Height。
function isElementPartiallyInViewport(el) { //special bonus for those using jQuery if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0]; var rect = el.getBoundingClientRect(); // DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 } var windowHeight = (window.innerHeight || document.documentElement.clientHeight); var windowWidth = (window.innerWidth || document.documentElement.clientWidth); // http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap var vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0); var horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0); return (vertInView && horInView); } // http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport function isElementInViewport (el) { //special bonus for those using jQuery if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0]; var rect = el.getBoundingClientRect(); var windowHeight = (window.innerHeight || document.documentElement.clientHeight); var windowWidth = (window.innerWidth || document.documentElement.clientWidth); return ( (rect.left >= 0) && (rect.top >= 0) && ((rect.left + rect.width) <= windowWidth) && ((rect.top + rect.height) <= windowHeight) ); } function fnIsVis(ele) { var inVpFull = isElementInViewport(ele); var inVpPartial = isElementPartiallyInViewport(ele); console.clear(); console.log("Fully in viewport: " + inVpFull); console.log("Partially in viewport: " + inVpPartial); }
testing用例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>Test</title> <!-- <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script src="scrollMonitor.js"></script> --> <script type="text/javascript"> function isElementPartiallyInViewport(el) { //special bonus for those using jQuery if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0]; var rect = el.getBoundingClientRect(); // DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 } var windowHeight = (window.innerHeight || document.documentElement.clientHeight); var windowWidth = (window.innerWidth || document.documentElement.clientWidth); // http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap var vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0); var horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0); return (vertInView && horInView); } // http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport function isElementInViewport (el) { //special bonus for those using jQuery if (typeof jQuery !== 'undefined' && el instanceof jQuery) el = el[0]; var rect = el.getBoundingClientRect(); var windowHeight = (window.innerHeight || document.documentElement.clientHeight); var windowWidth = (window.innerWidth || document.documentElement.clientWidth); return ( (rect.left >= 0) && (rect.top >= 0) && ((rect.left + rect.width) <= windowWidth) && ((rect.top + rect.height) <= windowHeight) ); } function fnIsVis(ele) { var inVpFull = isElementInViewport(ele); var inVpPartial = isElementPartiallyInViewport(ele); console.clear(); console.log("Fully in viewport: " + inVpFull); console.log("Partially in viewport: " + inVpPartial); } // var scrollLeft = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft, // var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop; </script> </head> <body> <div style="display: block; width: 2000px; height: 10000px; background-color: green;"> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" /> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <div style="background-color: crimson; display: inline-block; width: 800px; height: 500px;" ></div> <div id="myele" onclick="fnIsVis(this);" style="display: inline-block; width: 100px; height: 100px; background-color: hotpink;"> t </div> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <br /><br /><br /><br /><br /><br /> <input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" /> </div> <!-- <script type="text/javascript"> var element = document.getElementById("myele"); var watcher = scrollMonitor.create( element ); watcher.lock(); watcher.stateChange(function() { console.log("state changed"); // $(element).toggleClass('fixed', this.isAboveViewport) }); </script> --> </body> </html>
查看使用getBoundingClientRect的边缘的来源。 就像是:
function inViewport (el) { var r, html; if ( !el || 1 !== el.nodeType ) { return false; } html = document.documentElement; r = el.getBoundingClientRect(); return ( !!r && r.bottom >= 0 && r.right >= 0 && r.top <= html.clientHeight && r.left <= html.clientWidth ); }
如果元素的任何部分位于视口中,则返回true
。
我的更短更快的版本。
function isElementOutViewport (el) { var rect = el.getBoundingClientRect(); return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight; }
根据需要添加jsFiddle https://jsfiddle.net/on1g619L/1/
我发现有一个麻烦的是没有一个jQuery
中心版本的function可用。 当我遇到丹的解决scheme时,我发现有机会为喜欢用jQuery
OO编程的人们提供一些东西。 一定要向上滚动,然后在Dan的代码上打个招呼。 它的好和活泼,像我的魅力。
bada bing bada繁荣
$.fn.inView = function(){ if(!this.length) return false; var rect = this.get(0).getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && rect.right <= (window.innerWidth || document.documentElement.clientWidth) ); }; //additional examples for other use cases //true false whether an array of elements are all in view $.fn.allInView = function(){ var all = []; this.forEach(function(){ all.push( $(this).inView() ); }); return all.indexOf(false) === -1; }; //only the class elements in view $('.some-class').filter(function(){ return $(this).inView(); }); //only the class elements not in view $('.some-class').filter(function(){ return !$(this).inView(); });
用法
$(window).on('scroll',function(){ if( $('footer').inView() ) { // do cool stuff } });
http://www.appelsiini.net/projects/viewport
非常容易使用的插件,只需使用:in-viewport
我发现这里接受的答案对于大多数用例来说过于复杂。 这段代码很好地完成了这个工作(使用JQuery),并区分完全可见和部分可见的元素。
var element = $("#element"); var topOfElement = element.offset().top; var bottomOfElement = element.offset().top + element.outerHeight(true); var $window = $(window); $window.bind('scroll', function() { var scrollTopPosition = $window.scrollTop()+$window.height(); var windowScrollTop = $window.scrollTop() if( windowScrollTop > topOfElement && windowScrollTop < bottomOfElement) { // Element is partially visible (above viewable area) console.log("Element is partially visible (above viewable area)"); }else if( windowScrollTop > bottomOfElement && windowScrollTop > topOfElement ) { // Element is hidden (above viewable area) console.log("Element is hidden (above viewable area)"); }else if( scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement ) { // Element is hidden (below viewable area) console.log("Element is hidden (below viewable area)"); }else if( scrollTopPosition < bottomOfElement && scrollTopPosition > topOfElement ) { // Element is partially visible (below viewable area) console.log("Element is partially visible (below viewable area)"); }else{ // Element is completely visible console.log("Element is completely visible"); } });
取决于可见的含义。 如果您的意思是当前显示在页面上,给定滚动位置,您可以根据元素y偏移量和当前滚动位置计算它。
根据上面的@ dan的解决scheme( https://stackoverflow.com/a/7557433/5628 ),我有一个清理实施的步骤,以便在同一页面上多次使用它更容易:
$(function() { $(window).on('load resize scroll', function() { addClassToElementInViewport($('.bug-icon'), 'animate-bug-icon'); addClassToElementInViewport($('.another-thing'), 'animate-thing'); // 👏 repeat as needed ... }); function addClassToElementInViewport(element, newClass) { if (inViewport(element)) { element.addClass(newClass); } } function inViewport(element) { if (typeof jQuery === "function" && element instanceof jQuery) { element = element[0]; } var elementBounds = element.getBoundingClientRect(); return ( elementBounds.top >= 0 && elementBounds.left >= 0 && elementBounds.bottom <= $(window).height() && elementBounds.right <= $(window).width() ); } });
我使用它的方式是当元素滚动到视图中时,我添加了一个触发css关键帧animation的类。 这非常直接,当你在页面上有10多件有条件的animation时,效果尤其好。
希望它有帮助!
我认为这是一个更实用的方法。 Dan的答案在recursion上下文中不起作用。
这个函数解决了当你的元素在其他人可滚动div的问题,通过testing任何级别recursion的HTML标签,并停在第一个假。
/** * fullVisible=true only returns true if the all object rect is visible */ function isReallyVisible(el, fullVisible) { if ( el.tagName == "HTML" ) return true; var parentRect=el.parentNode.getBoundingClientRect(); var rect = arguments[2] || el.getBoundingClientRect(); return ( ( fullVisible ? rect.top >= parentRect.top : rect.bottom > parentRect.top ) && ( fullVisible ? rect.left >= parentRect.left : rect.right > parentRect.left ) && ( fullVisible ? rect.bottom <= parentRect.bottom : rect.top < parentRect.bottom ) && ( fullVisible ? rect.right <= parentRect.right : rect.left < parentRect.right ) && isReallyVisible(el.parentNode, fullVisible, rect) ); };
我在这里遇到的所有答案只检查元素是否位于当前视口内 。 但这并不意味着它是可见的 。
如果给定元素在内容溢出的div内,并且滚动出视图,该怎么办?
为了解决这个问题,你必须检查元素是否被所有父母包含。
我的解决scheme确实如此:
它还允许您指定多less元素必须可见。
Element.prototype.isVisible = function(percentX, percentY){ var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals if(percentX == null){ percentX = 100; } if(percentY == null){ percentY = 100; } var elementRect = this.getBoundingClientRect(); var parentRects = []; var element = this; while(element.parentElement != null){ parentRects.push(element.parentElement.getBoundingClientRect()); element = element.parentElement; } var visibleInAllParents = parentRects.every(function(parentRect){ var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left); var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top); var visiblePercentageX = visiblePixelX / elementRect.width * 100; var visiblePercentageY = visiblePixelY / elementRect.height * 100; return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY; }); return visibleInAllParents; };
这个解决scheme忽略了一个事实,即元素可能由于其他事实而不可见,例如opacity: 0
。
我已经在Chrome和Internet Explorer 11中testing了这个解决scheme。
这是我的解决scheme,它将工作,如果一个元素被隐藏在一个可卷动的容器内。
这里有一个演示 (尝试重新调整窗口的大小)
var visibleY = function(el){ var top = el.getBoundingClientRect().top, rect, el = el.parentNode; do { rect = el.getBoundingClientRect(); if (top <= rect.bottom === false) return false; el = el.parentNode; } while (el != document.body); // Check its within the document viewport return top <= document.documentElement.clientHeight; };
我只需要检查它是否在Y轴上可见(对于滚动ajax加载更多的loggingfunction)。
更好的解决scheme:
function getViewportSize(w) { var w = w || window; if(w.innerWidth != null) return {w:w.innerWidth, h:w.innerHeight}; var d = w.document; if (document.compatMode == "CSS1Compat") { return { w: d.documentElement.clientWidth, h: d.documentElement.clientHeight }; } return { w: d.body.clientWidth, h: d.body.clientWidth }; } function isViewportVisible(e) { var box = e.getBoundingClientRect(); var height = box.height || (box.bottom - box.top); var width = box.width || (box.right - box.left); var viewport = getViewportSize(); if(!height || !width) return false; if(box.top > viewport.h || box.bottom < 0) return false; if(box.right < 0 || box.left > viewport.w) return false; return true; }
检查元素是否至less部分在视图中(垂直尺寸):
function inView(element) { var box = element.getBoundingClientRect(); return inViewBox(box); } function inViewBox(box) { return ((box.bottom < 0) || (box.top > getWindowSize().h)) ? false : true; } function getWindowSize() { return { w: document.body.offsetWidth || document.documentElement.offsetWidth || window.innerWidth, h: document.body.offsetHeight || document.documentElement.offsetHeight || window.innerHeight} }
我有同样的问题,并通过使用getBoundingClientRect()计算出来。 这个代码是完全“通用的”,只需要编写一次就可以工作(你不必为每个你想知道的元素在视口中写出)。 此代码只检查是否在视口中垂直不水平 。 在这种情况下,variables(数组)“元素”将视图中垂直检查的所有元素保存在视口中,因此可以抓取任何您想要的元素并将其存储在此处。 'for循环'遍历每个元素,并检查它是否在视口中是垂直的。 这个代码每次用户滚动时执行! 如果getBoudingClientRect()。top小于3/4视口(该元素是视口中的四分之一),它将在“视口”中注册。 由于代码是通用的,您将需要知道“哪个”元素在视口中。 要发现这一点,你可以通过自定义属性,节点名称,ID,类名等等来确定它。 这里是我的代码(告诉我,如果它不工作,它已经在IE 11,FireFox 40.0.3,Chrome版本45.0.2454.85米,Opera 31.0.1889.174和边缘与Windows 10,[非Safari] )…
//scrolling handlers... window.onscroll = function(){ var elements = document.getElementById('whatever').getElementsByClassName('whatever'); for(var i = 0; i != elements.length; i++) { if(elements[i].getBoundingClientRect().top <= window.innerHeight*0.75 && elements[i].getBoundingClientRect().top > 0) { console.log(elements[i].nodeName + ' ' + elements[i].className + ' ' + elements[i].id + ' is in the viewport; proceed with whatever code you want to do here.'); } };
希望这有助于某人:-)
为我工作的简单而小巧的解决scheme。
示例您想要查看元素是否在具有溢出滚动的父元素中可见。
$(window).on('scroll', function () { var container = $('#sidebar'); var containerHeight = container.height(); var scrollPosition = $('#row1).offset().top - container.offset().top; if (containerHeight < scrollPosition) { console.log('not visible'); } else { console.log('visible'); } }
我使用这个函数(它只会检查y是否被屏蔽,因为大部分时间x不是必需的)
function elementInViewport(el) { var elinfo = { "top":el.offsetTop, "height":el.offsetHeight, }; if (elinfo.top + elinfo.height < window.pageYOffset || elinfo.top > window.pageYOffset + window.innerHeight) { return false; } else { return true; } }
对于一个类似的挑战,我真的很喜欢这个为scrollIntoViewIfNeeded()公开一个polyfill的 要点 。
所有必要的功夫需要回答在这个区块内:
var parent = this.parentNode, parentComputedStyle = window.getComputedStyle(parent, null), parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')), parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')), overTop = this.offsetTop - parent.offsetTop < parent.scrollTop, overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight), overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft, overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth), alignWithTop = overTop && !overBottom;
this
是指你想知道的元素,如果它是overTop
或overBottom
– 只是应该得到漂移…
我想要一个简单的jQuery解决scheme(只检查垂直滚动),所以我修改了Adam Rehals的代码。 此示例单击视口中的所有button,每秒检查5次。 (button点击时button被禁用)
$(function () { var loadButtons = $('.btn-load-more'); function clickButtonsIfInViewport() { loadButtons.each(function () { var element = $(this); var elementOffset = element.offset(); var elementTop = elementOffset.top; var elementBottom = elementOffset.top + element.outerHeight(true); var windowTop = $window.scrollTop(); var windowBottom = windowTop + $window.height(); if (windowTop > elementBottom || windowBottom < elementTop) { return; } element.click(); }); } setInterval(clickButtonsIfInViewport, 200); });