web-dev-qa-db-fra.com

Comment vérifier si l'élément est visible après le défilement?

Je charge des éléments via AJAX. Certaines ne sont visibles que si vous faites défiler la page.
Est-il possible de savoir si un élément est maintenant dans la partie visible de la page?

1021
yoavf

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

Fonction utilitaire simple .__ Cela vous permettra d’appeler une fonction utilitaire qui accepte l’élément recherché et si vous souhaitez que l’élément soit entièrement ou partiellement visible.

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');
}
1177
Scott Dowding

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

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

Imite un événement "apparaître" personnalisé, qui se déclenche lorsqu'un élément défile dans la vue ou devient visible par l'utilisateur.

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

Ce plugin peut être utilisé pour éviter les demandes inutiles de contenu caché ou situé en dehors de la zone d'affichage.

116
Joe Lencioni

Voici ma solution JavaScript pure qui fonctionne si elle est également cachée dans un conteneur pouvant défiler.

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

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: J'ai mis à jour la solution pour prendre en compte le défilement de l'élément afin qu'il soit masqué au-dessus du conteneur pouvant être défilé.EDIT 2018-10-08: Mise à jour pour gérer le défilement au-dessus de l'écran.

74
Ally

le plugin jQuery Waypoints 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 .

41
Fedir RYKHTIK

Que diriez-vous

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 visible comme ceci 

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

Ça marche très bien pour moi 

19
webicy

WebResourcesDepot wrote un script à charger lors du défilement qui utilise jQuery il y a quelque temps. Vous pouvez voir leur Démo en direct ici . Le bœuf de leur fonctionnalité était la suivante:

$(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
Sampson

Utilisation du ("nouveau") IntersectionObserver API

il est très facile et efficace de déterminer si un élément est visible dans la fenêtre. En utilisant un observateur, il n'est plus nécessaire de joindre un événement scroll et de vérifier manuellement le rappel de l'événement.

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

// provice 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>


Voir le tableau de support des navigateurs (non pris en charge dans IE/Safari)

12
vsync

La fonction géniale de Tweeked Scott Dowding pour mon besoin - Elle est utilisée pour déterminer si l'élément vient de défiler dans l'écran, c'est-à-dire son bord supérieur.

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

isScrolledIntoView est une fonction très nécessaire, je l'ai donc essayée, cela fonctionne pour des éléments dont la taille n'est pas supérieure à celle de la fenêtre, mais si l'élément est plus gros que la fenêtre, il ne fonctionne pas. Pour résoudre ce problème facilement changer la condition 

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

pour ça:

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

Voir la démo ici: http://jsfiddle.net/RRSmQ/

7
Robert

Il existe un plugin pour jQuery appelé inview qui ajoute un nouvel événement "inview".


Voici du code pour un plugin jQuery qui n'utilise pas les é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é cela dans un commentaire ici ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) par un type appelé James

6
ness-EE

Ceci prend en compte tout remplissage, bordure ou marge de l'élément ainsi que les éléments plus grands que la fenêtre elle-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
Brent Barbata
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));
}
6
Pascal Gagneur

La plupart des réponses ici ne tiennent pas compte du fait qu'un élément peut également être masqué car il est défilé 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é dans les 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;
};

Il vous permet également de spécifier à quel pourcentage il doit être visible dans chaque direction.
Il ne couvre pas la possibilité qu'il soit masqué en raison d'autres facteurs, tels que display: hidden.

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

6
Domysee

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>

Voir dans JSFiddle

5
Adrian P.

Plain Vanilla pour vérifier si l'élément (el) est visible dans un div à défilement (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
},

Utilisation avec jQuery:

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

J'avais besoin de vérifier la visibilité dans les éléments à l'intérieur du conteneur DIV à défilement

    //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);
    }
3
Pigmalión

En vous basant sur cette excellente réponse , vous pouvez la simplifier un peu plus loin en utilisant ES2015 +:

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

Si vous ne vous souciez pas du sommet sortant de la fenêtre et que vous vous souciez seulement du fond vu, vous pouvez le simplifier

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

ou même le one-liner

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

Modification de la réponse acceptée afin que l'élément de propriété d'affichage ait pour valeur autre que "none" afin que la qualité soit 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);
}
3
evanmcd

Si vous voulez modifier ce paramètre pour faire défiler un élément dans une autre division,

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
Samiya Akhtar

Un exemple basé sur cette réponse pour vérifier si un élément est visible à 75% (c’est-à-dire que moins de 25% de celui-ci est hors é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;
}
3
Brendan Nee

Vous pouvez utiliser le plugin jquery "onScreen" pour vérifier si l'élément est dans la fenêtre actuelle lorsque vous faites défiler . Le plugin définit le ": onScreen" du sélecteur sur true lorsque le sélecteur apparaît à 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
Vasuki Dileep

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 I.E. (au moins la version 6). Lisez les commentaires pour la compatibilité avec FF.

3
Romain Linsolas

Voici un moyen d’obtenir la même chose avec Mootools, qu’il soit horizontal, vertical 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);
}});
3
bmlkc

Cette méthode retournera true si une partie de l'élément est visible sur la page. Cela 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
Rafael Garcia

Modification simple pour div div (conteneur)

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

REMARQUE: cela ne fonctionne pas si l'élément est plus grand que le div à défilement.

2
Derrick J Wippler

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

afin que vous puissiez 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 ce code dans la fonction d'événement scroll, etc. pour le vérifier à chaque fois que l'utilisateur fait défiler la vue.

2
pie6k

Je cherchais un moyen de voir si l'élément serait bientôt visible, donc en prolongeant les extraits ci-dessus, j'ai réussi à le faire. pensais que je laisserais ça ici juste au cas où ça aiderait quelqu'un

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

scrollElement = vous pouvez passer window ou un élément parent qui a un scroll

offset = si vous voulez qu'il se déclenche lorsque l'élément est à 200px de distance avant de passer à l'écran, passez 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
Sonny Lloyd

J'ai adapté cette courte extension de la fonction jQuery, que vous pouvez utiliser librement (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
Lorenz Lo Sauer

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

Il fonctionne avec tous les types de conteneurs de défilement auxquels vous avez accès - fenêtre, éléments HTML, iframe intégré, fenêtre enfant engendrée - et est très flexible dans ce qu'il détecte ( visibilité totale ou partielle , zone de bordure ou zone de contenu , personnalisé zone de tolérance , etc ).

Une énorme suite de tests, généralement générée automatiquement, garantit son fonctionnement conforme à la version annoncée, navigateur multiple .

Donnez-lui un coup de feu si vous aimez: jQuery.isInView . Sinon, vous pourriez trouver de l'inspiration dans le code source, par exemple. ici .

1
hashchange

Une version plus efficace de cette réponse :

 /**
 * 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);
 }
1
John Doherty

Il y a plus de 30 réponses à cette question, et aucune d’entre elles n’utilise la solution JS étonnamment simple et pure que j’utilise. Il n'est pas nécessaire de charger jQuery juste pour résoudre ce problème, comme beaucoup d'autres le poussent.

Pour savoir si l'élément est dans la fenêtre, nous devons d'abord déterminer la position des éléments dans le corps. Nous n'avons pas besoin de faire cela récursivement comme je le pensais une fois. Au lieu de cela, nous pouvons utiliser element.getBoundingClientRect().

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

Cette valeur est la différence en Y entre le haut de l'objet et le haut du corps.

Nous devons ensuite dire si l'élément est visible. La plupart des implémentations demandent si l'élément complet se trouve dans la fenêtre d'affichage, c'est ce que nous allons couvrir.

Tout d’abord, la position la plus haute de la fenêtre est: window.scrollY.

Nous pouvons obtenir la position inférieure de la fenêtre en ajoutant la hauteur de la fenêtre à sa position supérieure:

var window_bottom_position = window.scrollY + window.innerHeight;

Permet de créer une fonction simple pour obtenir la première position de l'élément:

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

Cette fonction renvoie la position supérieure de l'élément dans la fenêtre ou 0 si vous lui transmettez autre chose qu'un élément avec la méthode .getBoundingClientRect(). Cette méthode existe depuis longtemps, vous ne devriez donc pas avoir à vous soucier de la non prise en charge par votre navigateur.

Maintenant, la première position de notre élément est:

var element_top_position = getElementWindowTop(element);

Et la position inférieure de l'élément est:

var element_bottom_position = element_top_position + element.clientHeight;

Nous pouvons maintenant déterminer si l'élément est dans la fenêtre en vérifiant si la position inférieure de l'élément est inférieure à la position supérieure de la fenêtre et en vérifiant si la position supérieure de l'élément est supérieure à la position inférieure de la fenêtre:

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

À partir de là, vous pouvez effectuer la logique pour ajouter ou supprimer une classe in-view sur votre élément, que vous pourrez ensuite gérer ultérieurement avec des effets de transition dans votre CSS.

Je suis absolument étonné de ne pas avoir trouvé cette solution ailleurs, mais je pense que c'est la solution la plus propre et la plus efficace, et que vous n'avez pas besoin de charger jQuery!

1
WebWanderer

Je voulais juste partager le fait que j'ai combiné cela avec mon script pour déplacer le div afin qu'il reste toujours en vue:

    $("#accordion").on('click', '.subLink', function(){
        var url = $(this).attr('src');
        updateFrame(url);
        scrollIntoView();
    });

    $(window).scroll(function(){
            changePos();
    });

  function scrollIntoView()
  {
        var docViewTop = $(window).scrollTop();
        var docViewBottom = docViewTop + $(window).height();    
        var elemTop = $("#divPos").offset().top;
        var elemBottom = elemTop + $("#divPos").height();               
        if (elemTop < docViewTop){
            $("#divPos").offset({top:docViewTop});
        }
   }

   function changePos(){        
    var scrTop = $(window).scrollTop();
    var frmHeight = $("#divPos").height()
        if ((scrTop < 200) || (frmHeight > 800)){   
         $("#divPos").attr("style","position:absolute;");
        }else{
          $("#divPos").attr("style","position:fixed;top:5px;");
        }
    }
1
tree

Fait un simple plugin détectant si l'élément est visible dans un conteneur à défilement

    $.fn.isVisible = function(){

      var win;
      if(!arguments[0])
      {
        console.error('Specify a target;');
        return false;
      }
      else
      {
        win = $(arguments[0]);
      }
      var viewport = {};
      var bounds = this.offset();
      bounds.right = bounds.left + this.outerWidth();
      bounds.bottom = bounds.top + this.outerHeight();
      viewport.bottom = win.height() + win.offset().top;
      return (!( bounds.top > viewport.bottom) && (win.offset().top < bounds.bottom));
    };

Appelez ça comme ça $('elem_to_check').isVisible('scrollable_container');

J'espère que ça va aider.

0
user3491125

Nous pouvons faire quelque chose comme ceci dans les navigateurs modernes en utilisant ES6 :

const isFullySeen = el => el &&
  typeof el.getBoundingClientRect === 'function' &&
  el.getBoundingClientRect()['bottom'] + window.scrollY <= 
    window.innerHeight + window.scrollY && 
  el.getBoundingClientRect()['top'] + window.scrollY <= 
    window.innerHeight + window.scrollY;
0
Alireza

Vérifie si l'élément est à l'écran plutôt que l'approche de la réponse acceptée qui vérifie si la div est entièrement à l'écran (ce qui ne fonctionnera pas si div est plus grand que l'écran) En Javascript pur:

/**
 * Checks if element is on the screen (Y axis only), returning true
 * even if the element is only partially on screen.
 *
 * @param element
 * @returns {boolean}
 */
function isOnScreenY(element) {
    var screen_top_position = window.scrollY;
    var screen_bottom_position = screen_top_position + window.innerHeight;

    var element_top_position = element.offsetTop;
    var element_bottom_position = element_top_position + element.offsetHeight;

    return (inRange(element_top_position, screen_top_position, screen_bottom_position)
    || inRange(element_bottom_position, screen_top_position, screen_bottom_position));
}

/**
 * Checks if x is in range (in-between) the
 * value of a and b (in that order). Also returns true
 * if equal to either value.
 *
 * @param x
 * @param a
 * @param b
 * @returns {boolean}
 */
function inRange(x, a, b) {
    return (x >= a && x <= b);
}
0
willsquire

Le seul plugin qui fonctionne systématiquement pour moi pour ce faire est: https://github.com/customd/jquery-visible

J'ai porté ce plugin sur GWT récemment car je ne voulais pas ajouter jquery en tant que dépendance uniquement pour utiliser le plugin. Voici mon (simple) port (incluant uniquement les fonctionnalités dont j'ai besoin pour mon cas d'utilisation):

public static boolean isVisible(Element e)
{
    //vp = viewPort, b = bottom, l = left, t = top, r = right
    int vpWidth   = Window.getClientWidth();
    int vpHeight = Window.getClientHeight();


    boolean tViz = ( e.getAbsoluteTop() >= 0 && e.getAbsoluteTop()<  vpHeight);
    boolean bViz = (e.getAbsoluteBottom() >  0 && e.getAbsoluteBottom() <= vpHeight);
    boolean lViz = (e.getAbsoluteLeft() >= 0 && e.getAbsoluteLeft() < vpWidth);
    boolean rViz = (e.getAbsoluteRight()  >  0 && e.getAbsoluteRight()  <= vpWidth);

    boolean vVisible   = tViz && bViz;
    boolean hVisible   = lViz && rViz;

    return hVisible && vVisible;
}
0
Click Upvote