滚动后如何检查元素是否可见?


1169

我正在通过AJAX加载元素。仅当您向下滚动页面时,其中一些才可见。
我有什么办法可以知道某个元素是否现在在页面的可见部分中?


42
他的意思是,他想要一种方法来知道给定元素是否显示在浏览器窗口中,或者用户是否需要滚动才能看到它。
罗曼·林索拉斯

1
要检查某个元素在容器中是否完全可见,只需添加一个额外的选择器参数并为其重新使用elem代码。 Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
2012年



1
所有答案都会触发重排,因此可能是瓶颈,如果支持,您可以大声喊叫IntersectionObserver。它将在现代浏览器上具有更好的性能,
jcubic

Answers:


1258

这应该可以解决问题:

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

简单实用程序功能 这将允许您调用实用程序功能,该功能接受您要查找的元素,以及您是否希望该元素完全可见或部分可见。

function Utils() {

}

Utils.prototype = {
    constructor: Utils,
    isElementInView: function (element, fullyInView) {
        var pageTop = $(window).scrollTop();
        var pageBottom = pageTop + $(window).height();
        var elementTop = $(element).offset().top;
        var elementBottom = elementTop + $(element).height();

        if (fullyInView === true) {
            return ((pageTop < elementTop) && (pageBottom > elementBottom));
        } else {
            return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
        }
    }
};

var Utils = new Utils();

用法

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}

52
请注意,这仅在文档是要滚动的元素时才起作用,即,您不检查滚动内部窗格中某个元素的可见性。
安德鲁B.

8
如何增加一点偏移量?
尔根·保罗

5
只有当我用工作window.innerHeight来代替
基督教的Schnorr

2
因为elemTop我曾经$(elem).position().topelemBottom我曾经elemTop + $(elem).outerHeight(true)
萨拉·弗赛尔斯

13
对于:“视图中元素的任何部分”,我使用了((((elemTop> = docViewTop)&&(elemTop <= docViewBottom))||((elemBottom> = docViewTop)&&(elemBottom <= docViewBottom)))
Grizly 2014年

415

香草的答案

function isScrolledIntoView(el) {
    var rect = el.getBoundingClientRect();
    var elemTop = rect.top;
    var elemBottom = rect.bottom;

    // Only completely visible elements return true:
    var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
    // Partially visible elements return true:
    //isVisible = elemTop < window.innerHeight && elemBottom >= 0;
    return isVisible;
}

27
这不是isVisible = elementTop < window.innerHeight && elementBottom >= 0吗?否则,屏幕上一半的元素将返回false。
gman 2015年

7
没有。我检查某些元素在页面上是否完全可见。如果您想检查某部分的可见性-您可以自定义此代码段。
bravedick

15
我发现此答案的表现要好于所选答案。也更简单。
亚当·威尼西亚

12
与批准的答案相比,这在数百个元素上的表现要好得多。
ncla

5
看到一个小提琴在这里演示-jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud

122

更新:使用IntersectionObserver


到目前为止,我发现的最好方法是 jQuery出现插件。奇迹般有效。

模仿一个自定义的“出现”事件,该事件在元素滚动到视图中或以其他方式对用户可见时触发。

$('#foo').appear(function() {
  $(this).text('Hello world');
});

该插件可用于防止对隐藏或可见区域之外的内容进行不必要的请求。


30
毫无疑问,这是一个很棒的插件,但是不能回答问题。
乔恩·亚当斯

5
尽管jQuery外观插件非常适合主页区域中的内容,但不幸的是,它具有固定大小的滚动div溢出问题。当绑定元素位于页面的可查看区域之内但位于div的可见区域之外时,该事件可能过早触发,然后当该元素在div中出现时,不会按预期触发。
彼得

17
有消失的插件吗?
Shamoon

3
@Shamoon检查的来源appear plugin,您可能只需要在!某个地方添加一个disappear插件即可。
Lucky Soni 2014年

5
值得注意的是,这不适用于jQuery 1.11.X github.com/morr/jquery.appear/issues/37
Jason Parham

86

这是我的纯JavaScript解决方案,如果它也隐藏在可滚动容器中,则可以使用。

此处演示(也尝试调整窗口大小)

var visibleY = function(el){
  var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
    el = el.parentNode
  // Check if bottom of the element is off the page
  if (rect.bottom < 0) return false
  // Check its within the document viewport
  if (top > document.documentElement.clientHeight) return false
  do {
    rect = el.getBoundingClientRect()
    if (top <= rect.bottom === false) return false
    // Check if the element is out of view due to a container scrolling
    if ((top + height) <= rect.top) return false
    el = el.parentNode
  } while (el != document.body)
  return true
};

EDIT 2016-03-26:我已经更新了解决方案,以解决滚动到元素上方的问题,因此该元素隐藏在可滚动容器顶部的上方。 EDIT 2018-10-08:更新为在屏幕上方滚动出视图时进行处理。


谢谢,也许更好的是 return top <= document.documentElement.clientHeight && top >= 0;
优素福Salimpour

16
+1这是考虑到元素的递归性质的唯一编码(即不是第三方)答案。我已经扩展到可以处理水平,垂直和页面滚动:jsfiddle.net/9nuqpgqa
Pebbl 2014年

3
此解决方案仅检查元素的顶部。如果第一个顶部像素可见,则即使其余部分不可见,它也将返回true。要检查整个元素是否可见,还需要检查bottom属性。
Wojciech Jakubas,2016年

2
是的,整洁!用于帮助编写此答案(以js注释表示功劳)。
Roamer-1888

失踪 ; 在循环中第二个“返回假”之后
Mikhail Ramendik '17

45

使用IntersectionObserver API(现代浏览器中的本机)

通过使用观察者,可以轻松高效地确定元素在viewpor或任何可滚动容器中是否可见

消除了附加scroll事件和手动检查事件回调的需要,从而提高了效率:

// this is the target which is observed
var target = document.querySelector('div');

// configure the intersection observer instance
var intersectionObserverOptions = {
  root: null,
  rootMargin: '150px',
  threshold: 1.0
}
    
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);

// provide the observer with a target
observer.observe(target);

function onIntersection(entries){
  entries.forEach(entry => {
    console.clear();
    console.log(entry.intersectionRatio)
    target.classList.toggle('visible', entry.intersectionRatio > 0);
    
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {
      // Stop watching 
      // observer.unobserve(entry.target);
    }
  });
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class='box'></div>


查看浏览器支持表(IE / Safari中不支持)


4
谢谢!这对我的作品,也得到了它在IE11正与github.com/w3c/IntersectionObserver
马特·威尔逊

迄今为止最好的解决方案。在没有polyfill的IE11中工作!
Fabian von Ellerts

请注意,不幸的是,iOS / macOS Safari不支持此STILL。如果选择填充,请确保检查性能问题,因为这是一个很大的用户群体
Leland

@Leland-这取决于项目。对于我所有的项目,这是一个绝对0用户组。我不是建立网站而是建立网络系统;)
vsync

我试图在几个元素上循环运行此,但它不起作用。有任何想法吗?我将元素添加到该循环中的目标。
Sascha Grindau

42

jQuery Waypoints插件在这里非常好用。

$('.entry').waypoint(function() {
   alert('You have scrolled to an entry.');
});

插件站点上有一些示例。


3
对我来说,它只能抵消使用 $('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' });
leymannx

21

怎么样

function isInView(elem){
   return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}

之后,一旦元素出现在视图中,您就可以触发所需的任何操作

$(window).scroll(function(){
   if (isInView($('.classOfDivToCheck')))
      //fire whatever you what 
      dothis();
})

对我来说很好


1
这对我有用,但是我在stackoverflow.com/questions/487073/…上使用了似乎更完整的isScrolledIntoView函数:
Meetai.com 2014年

3
我认为应该是$(window).scrollTop()<$(elem).offset()。top + $(elem).height();
年轻,

我的修改是这样的:`return $(window).scrollTop()+ $(window).height()> $(elem).offset()。top + $(elem).height(); `
bubencode

15

WebResourcesDepot编写了一个脚本,该脚本在滚动时使用jQuery 进行加载。您可以在此处查看他们的现场演示。他们功能的主要部分是:

$(window).scroll(function(){
  if  ($(window).scrollTop() == $(document).height() - $(window).height()){
    lastAddedLiveFunc();
  }
});

function lastAddedLiveFunc() { 
  $('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
  $.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
    function(data){
        if (data != "") {
          $(".wrdLatest:last").after(data);         
        }
      $('div#lastPostsLoader').empty();
    });
};

15

根据我的需求,Tweeked的Scott Dowding的出色功能-用于查找元素是否刚刚滚动到屏幕(即它的顶部边缘)中。

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}

12

普通香草检查元素(el)在可滚动div(holder)中是否可见

function isElementVisible (el, holder) {
  holder = holder || document.body
  const { top, bottom, height } = el.getBoundingClientRect()
  const holderRect = holder.getBoundingClientRect()

  return top <= holderRect.top
    ? holderRect.top - top <= height
    : bottom - holderRect.bottom <= height
},

jQuery的用法:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);

2
在单页面应用程序时代,检查一个元素在窗口之外的其他元素中是否可见已变得越来越普遍。这就是为什么我对此表示赞同。
H狗

8

isScrolledIntoView是一个非常需要的函数,因此我尝试了它,它适用于不比视口高的元素,但是如果该元素较大,则视口不起作用。要解决此问题,请轻松更改条件

return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

对此:

return (docViewBottom >= elemTop && docViewTop <= elemBottom);

在此处查看演示:http : //jsfiddle.net/RRSmQ/


8

此处的大多数答案都没有考虑到元素也可以隐藏的原因,因为它滚动到div的视图之外,不仅滚动到整个页面。

为了解决这种可能性,您基本上必须检查该元素是否位于其每个父元素的边界内。

该解决方案正是这样做的:

function(element, 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 = element.getBoundingClientRect();
    var parentRects = [];

    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;
};

它还可以让您指定在每个方向上可见的百分比。
它不包括由于其他因素(例如:display: hidden

这应该在所有主流浏览器中都可以使用,因为它仅使用getBoundingClientRect。我亲自在Chrome和Internet Explorer 11中对其进行了测试。


感谢您提供此代码。我不知道在这种情况下,如果您有多个嵌套的可滚​​动元素,如何在滚动上添加事件侦听器?似乎仅将侦听器添加到窗口是不够的,我们是否必须遍历到顶级父级才能将侦听器添加到每个可滚动容器?
mr1031011 '18

@ mr1031011应该有可能将处理程序添加到窗口,然后检查目标以标识已滚动的容器。
Domysee '18

对,它不适用于@vanowm给出的示例,
mr1031011 '18 -10-26

7
function isScrolledIntoView(elem) {
    var docViewTop = $(window).scrollTop(),
        docViewBottom = docViewTop + $(window).height(),
        elemTop = $(elem).offset().top,
     elemBottom = elemTop + $(elem).height();
   //Is more than half of the element visible
   return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}

7

这是来自http://web-profile.com.ua/的另一种解决方案

<script type="text/javascript">
$.fn.is_on_screen = function(){
    var win = $(window);
    var viewport = {
        top : win.scrollTop(),
        left : win.scrollLeft()
    };
    viewport.right = viewport.left + win.width();
    viewport.bottom = viewport.top + win.height();

    var bounds = this.offset();
    bounds.right = bounds.left + this.outerWidth();
    bounds.bottom = bounds.top + this.outerHeight();

    return (!(viewport.right < bounds.left || viewport.left > bounds.right ||    viewport.bottom < bounds.top || viewport.top > bounds.bottom));
 };

if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info       
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
$(window).scroll(function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
});
</script>

JSFiddle查看


7

这将考虑元素所具有的任何填充,边框或边距以及大于视口本身的元素。

function inViewport($ele) {
    var lBound = $(window).scrollTop(),
        uBound = lBound + $(window).height(),
        top = $ele.offset().top,
        bottom = top + $ele.outerHeight(true);

    return (top > lBound && top < uBound)
        || (bottom > lBound && bottom < uBound)
        || (lBound >= top && lBound <= bottom)
        || (uBound >= top && uBound <= bottom);
}

调用它的方法是这样的:

var $myElement = $('#my-element'),
    canUserSeeIt = inViewport($myElement);

console.log(canUserSeeIt); // true, if element is visible; false otherwise

7

有一个名为inview的 jQuery插件,它添加了一个新的“ inview”事件。


这是不使用事件的jQuery插件的一些代码:

$.extend($.expr[':'],{
    inView: function(a) {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
            ot = $(a).offset().top,
            wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
        return ot > st && ($(a).height() + ot) < (st + wh);
    }
});

(function( $ ) {
    $.fn.inView = function() {
        var st = (document.documentElement.scrollTop || document.body.scrollTop),
        ot = $(this).offset().top,
        wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();

        return ot > st && ($(this).height() + ot) < (st + wh);
    };
})( jQuery );

我在一个叫做James的家伙的评论(http://remysharp.com/2009/01/26/element-in-view-event-plugin/)中发现了这一点


las,不再维护jQuery inview,并且不适用于当前版本的jQuery。
mikemaccana 2014年

1
JQuery的1对旧版浏览器的支持,新功能在jQuery的2
mikemaccana

由于页面已更新,因此链接未显示示例。
编程教授,

6

我需要检查可滚动DIV容器内元素的可见性

    //p = DIV container scrollable
    //e = element
    function visible_in_container(p, e) {
        var z = p.getBoundingClientRect();
        var r = e.getBoundingClientRect();

        // Check style visiblilty and off-limits
        return e.style.opacity > 0 && e.style.display !== 'none' &&
               e.style.visibility !== 'hidden' &&
               !(r.top > z.bottom || r.bottom < z.top ||
                 r.left > z.right || r.right < z.left);
    }

如果将更e.style.opacity > 0改为(!e.style.opacity || e.style.opacity > 0),这对我有用,因为默认情况下,它是FF中对我来说为空字符串。
布雷特·扎米尔

6

这个好答案的基础上,您可以使用ES2015 +进一步简化它:

function isScrolledIntoView(el) {
  const { top, bottom } = el.getBoundingClientRect()
  return top >= 0 && bottom <= window.innerHeight
}

如果您不在乎顶部从窗口中伸出,而只是在乎底部已被查看,则可以简化为

function isSeen(el) {
  return el.getBoundingClientRect().bottom <= window.innerHeight
}

甚至单线

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight

4

滚动时,可以使用jquery插件“ onScreen”检查元素是否在当前视口中。当选择器出现在屏幕上时,插件会将选择器的“:onScreen”设置为true。这是您可以包含在项目中的插件的链接。” http://benpickles.github.io/onScreen/jquery.onscreen.min.js

您可以尝试以下对我有用的示例。

$(document).scroll(function() {
    if($("#div2").is(':onScreen')) {
        console.log("Element appeared on Screen");
        //do all your stuffs here when element is visible.
    }
    else {
        console.log("Element not on Screen");
        //do all your stuffs here when element is not visible.
    }
});

HTML代码:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>

CSS:

#div1 {
    background-color: red;
}
#div2 {
    background-color: green;
}

3

我的应用程序中有这种方法,但是它不使用jQuery:

/* Get the TOP position of a given element. */
function getPositionTop(element){
    var offset = 0;
    while(element) {
        offset += element["offsetTop"];
        element = element.offsetParent;
    }
    return offset;
}

/* Is a given element is visible or not? */
function isElementVisible(eltId) {
    var elt = document.getElementById(eltId);
    if (!elt) {
        // Element not found.
        return false;
    }
    // Get the top and bottom position of the given element.
    var posTop = getPositionTop(elt);
    var posBottom = posTop + elt.offsetHeight;
    // Get the top and bottom position of the *visible* part of the window.
    var visibleTop = document.body.scrollTop;
    var visibleBottom = visibleTop + document.documentElement.offsetHeight;
    return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}

编辑:此方法适用于IE(至少为版本6)。阅读注释以了解与FF的兼容性。


2
由于某些原因,document.body.scrollTop始终返回0(在ff3上)。将其更改为var visibleTop =(document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop);
yoavf

抱歉 我的应用程序只能在IE 6中运行(是的,我不太幸运:(),所以我从未在FF中对此进行过测试...
Romain Linsolas 09年

如果正确的话,这将是最好的答案。将您的一行更正为:var visibleBottom = visibleTop + window.innerHeight;我不使用jQuery,您帮助我找到了正确的答案。
Bitterblue

3

如果您想对此进行调整以在另一个div中滚动项目,

function isScrolledIntoView (elem, divID) 

{

    var docViewTop = $('#' + divID).scrollTop();


    var docViewBottom = docViewTop + $('#' + divID).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 
}

3

修改了接受的答案,以便该元素必须将其显示属性设置为“ none”以外的其他属性,以确保可见质量。

function isScrolledIntoView(elem) {
   var docViewTop = $(window).scrollTop();
  var docViewBottom = docViewTop + $(window).height();

  var elemTop = $(elem).offset().top;
  var elemBottom = elemTop + $(elem).height();
  var elemDisplayNotNone = $(elem).css("display") !== "none";

  return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}

3

这是一种使用Mootools在水平,垂直或两者上实现相同目的的方法。

Element.implement({
inVerticalView: function (full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewTop = windowScroll.y;
    var docViewBottom = docViewTop + windowSize.y;
    var elemTop = elementPosition.y;
    var elemBottom = elemTop + elementSize.y;

    if (full) {
        return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
            && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
    } else {
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }
},
inHorizontalView: function(full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewLeft = windowScroll.x;
    var docViewRight = docViewLeft + windowSize.x;
    var elemLeft = elementPosition.x;
    var elemRight = elemLeft + elementSize.x;

    if (full) {
        return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
            && (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
    } else {
        return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
    }
},
inView: function(full) {
    return this.inHorizontalView(full) && this.inVerticalView(full);
}});

3

基于此答案的示例用于检查某个元素是否可见75%(即小于25%的元素不在屏幕上)。

function isScrolledIntoView(el) {
  // check for 75% visible
  var percentVisible = 0.75;
  var elemTop = el.getBoundingClientRect().top;
  var elemBottom = el.getBoundingClientRect().bottom;
  var elemHeight = el.getBoundingClientRect().height;
  var overhang = elemHeight * (1 - percentVisible);

  var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
  return isVisible;
}

3

这个问题有30多个答案,没有一个答案使用我一直在使用的极其简单的纯JS解决方案。正如许多其他人所推动的那样,无需加载jQuery即可解决此问题。

为了确定元素是否在视口内,我们必须首先确定元素在体内的位置。正如我曾经想过的那样,我们不需要递归执行此操作。相反,我们可以使用element.getBoundingClientRect()

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

该值是对象顶部和身体顶部之间的Y差。

然后,我们必须判断该元素是否在视图内。大多数实现都会询问full元素是否在视口内,因此这就是我们要介绍的内容。

首先,窗口的顶部位置是:window.scrollY

我们可以通过将窗口的高度添加到其顶部位置来获得窗口的底部位置:

var window_bottom_position = window.scrollY + window.innerHeight;

让我们创建一个简单的函数来获取元素的最高位置:

function getElementWindowTop(elem){
    return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

此函数将返回元素在窗口中的顶部位置,或者0如果您通过除元素之外的其他元素将其传递给其他对象,则该函数将返回。.getBoundingClientRect()。这种方法已经存在了很长时间,因此您不必担心浏览器不支持它。

现在,我们元素的最高位置是:

var element_top_position = getElementWindowTop(element);

和或元素的底部位置是:

var element_bottom_position = element_top_position + element.clientHeight;

现在,我们可以通过检查元素的底部位置是否低于视口的顶部位置,并检查元素的顶部位置是否高于视口的底部位置,来确定元素是否在视口中:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
    //element is in view
else
    //element is not in view

在这里,您可以执行逻辑以in-view在元素上添加或删除类,然后可以在CSS中使用过渡效果对其进行处理。

令我惊讶的是,我在其他任何地方都找不到该解决方案,但是我相信这是最干净,最有效的解决方案,它不需要您加载jQuery!


很好的解释!但是已经有完全符合您要求的答案
Domysee '17

1
@Domysee嗯,我以某种方式跳过了这一点。很公平。谢谢您指出这一点。很高兴看到以另一种方式完成此操作。
WebWanderer

3

此答案的更有效的版本:

 /**
 * Is element within visible region of a scrollable container
 * @param {HTMLElement} el - element to test
 * @returns {boolean} true if within visible region, otherwise false
 */
 function isScrolledIntoView(el) {
      var rect = el.getBoundingClientRect();
      return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
 }

2

如果元素的任何部分在页面上可见,则此方法将返回true。就我而言,它效果更好,可能会帮助其他人。

function isOnScreen(element) {
  var elementOffsetTop = element.offset().top;
  var elementHeight = element.height();

  var screenScrollTop = $(window).scrollTop();
  var screenHeight = $(window).height();

  var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
  var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;

  return scrollIsAboveElement && elementIsVisibleOnScreen;
}

2

滚动div(容器)的简单修改

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

注意:如果元素大于可滚动的div,则此方法不起作用。


2

我改编了这个简短的jQuery函数扩展,您可以随时使用(MIT许可证)。

/**
 * returns true if an element is visible, with decent performance
 * @param [scope] scope of the render-window instance; default: window
 * @returns {boolean}
 */
jQuery.fn.isOnScreen = function(scope){
    var element = this;
    if(!element){
        return;
    }
    var target = $(element);
    if(target.is(':visible') == false){
        return false;
    }
    scope = $(scope || window);
    var top = scope.scrollTop();
    var bot = top + scope.height();
    var elTop = target.offset().top;
    var elBot = elTop + target.height();

    return ((elBot <= bot) && (elTop >= top));
};

2

我已经为该任务编写了一个组件,该组件旨在以极快的速度处理大量元素(对于慢速移动设备上的 1000个元素,其调整时间<10ms)。

它适用于所有类型的滚动容器可以访问-窗口,HTML元素,嵌入的iframe,催生子窗口-并且是在哪呢检测(非常灵活的全部或部分的可见性边界框或内容框,自定义公差带)。

庞大的,主要是自动生成的测试套件可确保其像跨浏览器的广告一样工作

如果愿意,可以一下:jQuery.isInView。否则,您可能会在源代码中找到灵感,例如here

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.