スクロール後に要素が表示されるかどうかを確認する方法は?


1170

AJAX経由で要素を読み込んでいます。それらのいくつかは、ページを下にスクロールした場合にのみ表示されます。
要素がページの表示部分にあるかどうかを知る方法はありますか?


42
彼は、特定の要素がブラウザーウィンドウに表示されているかどうか、またはユーザーがそれを表示するためにスクロールする必要があるかどうかをメソッドに知らせたいことを意味します。
Romain Linsolas、2009年

1
要素がコンテナで完全に表示されるかどうかを確認するには、追加のセレクターパラメーターを追加し、その要素コードを再利用します。 Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
静物



1
すべての回答はリフローをトリガーするため、ボトルネックになる可能性があります。サポートされている場合はIntersectionObserverを使用するように叫びます。最新のブラウザーでのパフォーマンスが向上します
jcubic

回答:


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
これは、ドキュメントがスクロールされる要素である場合にのみ機能することに注意してください。つまり、スクロールする内部ペイン内の一部の要素の可視性をチェックしていません。
Andrew B.

8
少しオフセットを追加する方法?
ユルゲンポール

5
私がwindow.innerHeight代わりに使用した場合にのみ機能しました
Christian Schnorr 2014年

2
以下のためにelemTop私が使用$(elem).position().topしてのためにelemBottom私が使用しましたelemTop + $(elem).outerHeight(true)
サラベッセル2014年

13
「ビュー内の要素の任意の部分」の場合:(((elemTop> = docViewTop)&&(elemTop <= docViewBottom))||((elemBottom> = docViewTop)&&(elemBottom <= docViewBottom)))
グリズリー

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

7
番号。一部の要素がページに完全に表示されているかどうかを確認します。一部の可視性を確認したい場合-このスニペットをカスタマイズできます。
bravedick

15
この回答は、選択した回答よりも優れていることがわかりました。簡単です。
アダムベネチア

12
承認された回答と比較して、これは何百もの要素でwaaaayをはるかによく実行します。
ncla 2016

5
ここでデモンストレーションする小さなフィドルを参照してください-jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud

122

更新:IntersectionObserverを使用する


これまでに見つけた最良の方法は、jQuery表示プラグインです。魅力のように機能します。

要素がスクロールして表示されるか、ユーザーに表示されるときに発生するカスタムの「出現」イベントを模倣します。

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

このプラグインを使用すると、非表示になっている、または表示可能領域外にあるコンテンツに対する不要な要求を防止できます。


30
これは間違いなくクールなプラグインですが、質問の答えにはなりません。
Jon Adams

5
jQuery-appearプラグインはメインページ領域のコンテンツに適していますが、残念ながら、オーバーフローを伴う固定サイズのスクロールdivの問題があります。バインドされた要素がページの表示可能領域内にあるがdivの表示可能領域外にある場合、イベントは時期尚早に発生し、要素がdivに表示されたときに期待どおりに発生しない可能性があります。
ピーター

17
消えるプラグインはありますか?
Shamoon

3
@Shamoonでソースを確認します。プラグインを取得appear pluginするには、おそらく!どこかに追加する必要がありdisappearます。
Lucky Soni

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

編集2016-03-26:要素を超えてスクロールすることを考慮して、スクロール可能なコンテナーの上部に非表示になるようにソリューションを更新しました。 編集2018-10-08:画面の上にスクロールして表示されなくなったときに処理するように更新されました。


ありがとう、たぶんもっと良い return top <= document.documentElement.clientHeight && top >= 0;
ユセフ・サリンプール2014年

16
+1これは、要素の再帰的な性質を考慮した唯一のコード化された(つまり、サードパーティではない)回答でした。水平、垂直、ページスクロールを処理できるように拡張しました:jsfiddle.net/9nuqpgqa
Pebbl

3
このソリューションは、要素の上部のみをチェックします。最初の上部のピクセルが表示されている場合、アイテムの残りの部分が表示されていなくてもtrueを返します。要素全体が表示されているかどうかを確認するには、bottomプロパティも確認する必要があります。
Wojciech Jakubas 2016

2
はい、きちんと!この回答を書くのに役立ちます(jsコメントとしてのクレジット付き)。
Roamer-1888

行方不明; ループの2番目の「return false」の後
ミハイルラメンディク'19年

46

使用IntersectionObserver API(最近のブラウザでネイティブに)

オブザーバーを使用して、要素がビューポーに表示されるか、スクロール可能なコンテナーに表示されるかを判別するのは簡単で効率的です。

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
ありがとう!これは私にとってはうまくいき、github.com / w3c
Matt Wilson

断然最高のソリューションです。ポリフィルなしでIE11で動作しました!
Fabian von Ellerts

残念ながら、このSTILLはiOS / macOS Safariではサポートされていません。ポリフィルを選択する場合は、パフォーマンスの問題を必ず確認してください。これは、大規模なユーザーグループです
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
これは私には有効ですが、一見するとより完全な関数isScrolledIntoViewをstackoverflow.com/questions/487073/… :)で使用しました
Meetai.com

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

私の要件に合わせたTcotted 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

@ mr1031011ハンドラーをウィンドウに追加し、ターゲットをチェックして、スクロールされたコンテナーを識別できるようにする必要があります。
Domysee

右、@ vanowmの例では機能しません
mr1031011 '26 / 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」イベントを追加する、inview呼ばれるjQueryのプラグインがあります。


以下は、イベントを使用しない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/)でこれを見つけました


残念ながら、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の空の文字列になるため、これは機能します。
Brett Zamir 2014年

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 2009年

そのために残念。私のアプリケーションはIE 6でのみ実行する必要があります(そうです、私は幸運ではありません:()ので、これをFFでテストしたことはありません...
Romain Linsolas 2009年

これが正しければ、これがここでの最良の答えです。これにあなたの行の1つを訂正してください:var visibleBottom = visibleTop + window.innerHeight;私はjQueryを使用しておらず、正しい答えを見つけるのを手伝ってくれました。
Bitterblue 2013年

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

受け入れられた回答を変更して、要素の表示プロパティを「なし」以外に設定して、表示される品質にする必要があるようにしました。

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差です。

次に、要素がビュー内にあるかどうかを通知する必要があります。ほとんどの実装では、要素全体がビューポート内にあるかどうかを尋ねるので、これをカバーします。

まず、ウィンドウの一番上の位置はです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をロードする必要がないと信じています!


とてもいい説明!しかし、Allyの答えの
Domysee

1
@Domyseeうーん、なんとかスキップした。けっこうだ。指摘していただきありがとうございます。これが別の方法で行われるのを見るのは良いことです。
WebWanderer 2017

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要素で10ミリ秒未満の調整に)。

そして、それは(検出したものの中には非常に柔軟である-窓、HTML要素、埋め込まれたIFRAME、生まれた子ウィンドウ-それはあなたがアクセス権を持っているスクロールコンテナのすべてのタイプで動作する完全または部分的な可視性境界ボックス、またはコンテンツボックス、カスタムの公差域など)。

ほとんど自動生成された巨大なテストスイートは、アドバタイズされたクロスブラウザとして機能することを保証します。

必要に応じて試してください:jQuery.isInView。そうでなければ、ソースコードにインスピレーションを見つけるかもしれません、例えばここに

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.