Vérifier si l'élément est visible après le défilement

je charge des éléments via AJAX. Certains d'entre eux ne sont visibles que si vous faites défiler la page.

Est-il possible que je peux savoir si un élément est maintenant dans la partie visible de la page?

990
demandé sur Alexis King 2009-01-28 13:00:55

30 réponses

Cela devrait faire l'affaire:

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

Simple Fonction D'Utilité Cela vous permettra d'appeler une fonction utilitaire qui accepte l'élément que vous recherchez et si vous voulez que l'élément soit entièrement en vue ou partiellement.

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();

Utilisation

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

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}
1145
répondu Scott Dowding 2016-10-13 14:27:21

Cette réponse à la Vanille:

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;
}
307
répondu bravedick 2017-12-03 13:26:54

la meilleure méthode que j'ai trouvée jusqu'à présent est le jQuery appear plugin . Fonctionne comme un charme.

imite un événement personnalisé "appear", qui se déclenche lorsqu'un élément apparaît ou devient visible de toute autre manière pour l'utilisateur.

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

ce plugin peut être utilisé pour empêcher les demandes inutiles de contenu qui est caché ou en dehors de la zone visible.

114
répondu Joe Lencioni 2013-03-12 13:58:26

voici ma solution JavaScript pure qui fonctionne si elle est cachée dans un conteneur scrollable aussi.

Démo ici (essayez de redimensionner la fenêtre de trop)

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

MODIFIER 2016-03-26: j'ai mis à jour la solution pour tenir compte de défilement au-delà de l'élément de sorte qu'il est caché au-dessus de la mesure de défilement conteneur. MODIFIER 2018-10-08: mise à Jour pour gérer lorsque défile en dehors de la vue au-dessus de la écran.

66
répondu Ally 2018-10-08 03:11:57

jQuery Waypoints plugin va très bien ici.

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

il y a quelques exemples sur le site du plugin .

40
répondu Fedir RYKHTIK 2011-12-04 12:08:19

Que Diriez-vous de

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

après cela vous pouvez déclencher ce que vous voulez une fois que l'élément est en vue comme ceci

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

Qui fonctionne pour moi très bien

15
répondu webicy 2015-11-09 08:18:24

WebResourcesDepot écrit un script pour charger lors du défilement qui utilise jQuery il y a quelques temps. Vous pouvez voir leur démo Live ici . Le boeuf de leur fonctionnalité:

$(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();
    });
};
14
répondu Sampson 2009-01-28 14:14:48

Tweeked fonction cool de Scott Dowding pour mes besoins- ceci est utilisé pour trouver si l'élément vient de glisser dans l'écran I. c'est top edge .

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
12
répondu Snigdha Batra 2013-04-30 16:08:20

isScrolledIntoView est une fonction très utile, donc je l'ai essayé, il fonctionne pour des éléments pas plus haut que le viewport, mais si l'élément est plus grand que le viewport il ne fonctionne pas. Pour corriger cette facilement changer la condition

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

à ceci:

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

voir démo ici: http://jsfiddle.net/RRSmQ/

6
répondu Robert 2013-10-23 17:30:40

il s'agit de tout rembourrage, bordure ou marge de l'élément ainsi que des éléments plus grands que le support lui-même.

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

pour l'appeler utilisez quelque chose comme ceci:

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

console.log(canUserSeeIt); // true, if element is visible; false otherwise
6
répondu Brent Barbata 2015-01-08 17:00:02

la plupart des réponses ici ne tiennent pas compte du fait qu'un élément peut aussi être caché parce qu'il est égratigné hors de la vue d'un div, pas seulement de la page entière.

pour couvrir cette possibilité, vous devez essentiellement vérifier si l'élément est placé à l'intérieur des limites de chacun de ses parents.

Cette solution fait exactement cela:

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

permet également de spécifier à quel pourcentage il doit être visible dans chaque direction.

Il ne couvre pas la possibilité qu'il puisse être caché en raison d'autres facteurs, comme display: hidden .

cela devrait fonctionner dans tous les principaux navigateurs, car il utilise uniquement getBoundingClientRect . Je l'ai personnellement testé dans Chrome et Internet Explorer 11.

6
répondu Domysee 2016-11-02 09:40:40
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));
}
5
répondu Pascal Gagneur 2009-10-09 10:42:03

il y a un plugin pour jQuery appelé inview qui ajoute un nouvel événement" inview".


voici du code pour un plugin jQuery qui n'utilise pas d'événements:

$.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 );

j'ai trouvé ceci dans un commentaire ici ( http://remysharp.com/2009/01/26/element-in-view-event-plugin / ) par un type appelé James

5
répondu ness-EE 2018-06-04 11:41:26

vous pouvez faire usage de jQuery plugin" onScreen " pour vérifier si l'élément est dans le viewport courant lorsque vous faites défiler. Le plugin positionne le": onScreen " du sélecteur à true lorsque le sélecteur apparaît sur l'écran. C'est le lien pour le plugin que vous pouvez inclure dans votre projet. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "

Vous pouvez essayer l'exemple ci-dessous qui fonctionne pour moi.

$(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.
    }
});

code 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
répondu Vasuki Dileep 2015-03-04 11:34:51

construire à partir de cette grande réponse , vous pouvez la simplifier un peu plus en utilisant ES2015+:

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

si vous ne vous souciez pas que le haut sorte par la fenêtre et que vous vous souciez juste que le bas ait été vu, cela peut être simplifié par

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

ou encore le one-liner

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight
3
répondu rpearce 2017-05-23 12:02:47

vanille ordinaire pour vérifier si l'élément ( el ) est visible dans la division déroulable ( 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
},

Usage avec jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);
3
répondu Denis Matafonov 2018-10-10 20:46:32

j'ai une telle méthode dans mon application, mais elle n'utilise pas 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));
}

Edit : Cette méthode fonctionne bien pour les I. E. (au moins la version 6). Lire les commentaires pour la compatibilité avec FF.

2
répondu romaintaz 2009-01-28 14:04:59

si vous voulez modifier ceci pour faire défiler l'article dans une autre 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)); 
}
2
répondu Samiya Akhtar 2013-04-05 19:33:56

a modifié la réponse acceptée de façon à ce que la propriété display de l'élément soit définie à quelque chose d'autre que" none " à la qualité visible.

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);
}
2
répondu evanmcd 2013-09-16 20:02:56

Voici une autre solution de 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>

le Voir dans JSFiddle

2
répondu Adrian P. 2014-02-15 18:56:35

Voici une façon d'obtenir la même chose en utilisant des Mootools, à l'horizontale, à la verticale ou les deux.

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);
}});
2
répondu bmlkc 2014-06-14 20:59:43

j'avais besoin de vérifier la visibilité dans les éléments à L'intérieur du conteneur DIV contrôlable

    //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);
    }
2
répondu Pigmalión 2014-06-21 01:28:32

Cette méthode renvoie true si une partie de l'élément est visible sur la page. Il a mieux fonctionné dans mon cas et peut aider quelqu'un d'autre.

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
répondu Rafael Garcia 2014-08-15 14:23:50

Simple modification de défilement div (récipient)

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

NOTE: cela ne fonctionne pas si l'élément est plus grand que le div.

2
répondu Derrick J Wippler 2014-09-10 20:41:18

j'ai adapté cette extension de fonction jQuery courte, que vous pouvez vous sentir libre d'utiliser (licence 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
répondu Lorenz Lo Sauer 2015-01-23 11:50:53

un exemple basé sur cette réponse pour vérifier si un élément est visible à 75% (C.-à-d. que moins de 25% de l'élément est visible hors de l'écran).

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;
}
2
répondu Brendan Nee 2017-05-23 11:55:10

je cherchais un moyen de voir si l'élément va venir en vue prochainement, en étendant les extraits de code ci-dessus, j'ai réussi à le faire. pensé que je laisserais ici juste au cas où il aidera quelqu'un

elm = est l'élément que vous voulez vérifier est dans la vue

scrollElement = vous pouvez passer fenêtre ou un élément parent qui a un rouleau

offset = si vous voulez qu'il se déclenche lorsque l'élément est à 200px avant son dans l'écran puis passer 200

function isScrolledIntoView(elem, scrollElement, offset)
        {
            var $elem = $(elem);
            var $window = $(scrollElement);
            var docViewTop = $window.scrollTop();
            var docViewBottom = docViewTop + $window.height();
            var elemTop = $elem.offset().top;
            var elemBottom = elemTop + $elem.height();
            
            return (((elemBottom+offset) >= docViewBottom) && ((elemTop-offset) <= docViewTop)) || (((elemBottom-offset) <= docViewBottom) && ((elemTop+offset) >= docViewTop));
        }
2
répondu Sonny Lloyd 2015-08-21 10:46:42

je préfère utiliser jQuery expr

jQuery.extend(jQuery.expr[':'], {  
    inview: function (elem) {
        var t = $(elem);
        var offset = t.offset();
        var win = $(window); 
        var winST = win.scrollTop();
        var elHeight = t.outerHeight(true);

        if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {
            return true;    
        }    
        return false;  
    }
});

donc vous pouvez l'utiliser de cette façon

$(".my-elem:inview"); //returns only element that is in view
$(".my-elem").is(":inview"); //check if element is in view
$(".my-elem:inview").length; //check how many elements are in view

vous pouvez facilement ajouter un tel code dans scroll fonction d'événement etc. pour le vérifier chaque fois l'utilisateur fera défiler la vue.

2
répondu pie6k 2016-09-15 09:45:13

j'ai écrit un composant pour la tâche, conçu pour manipuler un grand nombre d'éléments extrêmement rapide (à l'air de <10ms pour 1000 éléments sur un mobile lent ).

il fonctionne avec chaque type de conteneur de rouleau que vous avez accès à-fenêtre, éléments HTML, iframe intégré, fenêtre enfant engendré – et est très flexible dans ce qu'il détecte ( pleine ou partielle visibilité , zone de bordure ou le contenu de la boîte , la coutume zone de tolérance , etc ).

une suite de test énorme, principalement générée automatiquement, garantit qu'elle fonctionne comme annoncé, cross-browser .

faites un essai si vous aimez: jQuery.isInView . Sinon, vous pourriez trouver l'inspiration dans le code source, par exemple ici .

1
répondu hashchange 2015-03-08 17:51:50