Erkennt, wenn Elemente innerhalb eines scrollbaren div-Elements nicht sichtbar sind

Lesezeit: 6 Minuten

Benutzer-Avatar
Ronny

Ich muss eine gute Lösung für das folgende Problem finden. Ich sehe viele Leute, die nach dem Tracking fragen, ob sich ein Element innerhalb oder außerhalb des Ansichtsports für die Seite oder das Browserfenster befindet. Ich muss in der Lage sein, diese Aktion zu replizieren, aber in einem DIV, das scrollt, zum Beispiel mit overflow:scroll. Kennt jemand ein gutes Beispiel für diese spezielle Aktion?

Danke im Voraus.

Benutzer-Avatar
Adam Reis

Hier ist eine reine Javascript-Version der akzeptierten Antwort, ohne sich auf jQuery zu verlassen, und mit einigen Korrekturen für die Erkennung von Teilansichten und Unterstützung für die Anzeige von außerhalb.

function checkInView(container, element, partial) {

    //Get container properties
    let cTop = container.scrollTop;
    let cBottom = cTop + container.clientHeight;

    //Get element properties
    let eTop = element.offsetTop;
    let eBottom = eTop + element.clientHeight;

    //Check if in view    
    let isTotal = (eTop >= cTop && eBottom <= cBottom);
    let isPartial = partial && (
      (eTop < cTop && eBottom > cTop) ||
      (eBottom > cBottom && eTop < cBottom)
    );

    //Return outcome
    return  (isTotal  || isPartial);
}

Und als Bonus stellt diese Funktion sicher, dass das Element sichtbar ist, wenn dies nicht der Fall ist (teilweise oder vollständig):

function ensureInView(container, element) {

    //Determine container top and bottom
    let cTop = container.scrollTop;
    let cBottom = cTop + container.clientHeight;

    //Determine element top and bottom
    let eTop = element.offsetTop;
    let eBottom = eTop + element.clientHeight;

    //Check if out of view
    if (eTop < cTop) {
      container.scrollTop -= (cTop - eTop);
    }
    else if (eBottom > cBottom) {
      container.scrollTop += (eBottom - cBottom);
    }
}

  • In Ihrer sureInView-Funktion sollte offsetTop hinzugefügt werden let cTop = container.scrollTop + container.offsetTop

    – Brian Völker

    27. März 2017 um 20:22 Uhr


  • Das scheint bei mir nicht zu funktionieren, es unterbricht tatsächlich die Funktion in meinem Anwendungsfall.

    – Adam Reis

    28. März 2017 um 23:07 Uhr

  • Was ist der Zweck von partial Feld ein checkInView?

    – oyalhi

    29. November 2018 um 15:29 Uhr

  • Das ist ein Flag, um zu prüfen, ob das Element teilweise oder vollständig sichtbar sein soll.

    – Adam Reis

    29. November 2018 um 20:47 Uhr

  • Jetzt gibt es das element.scrollIntoView() Funktion, die gut funktioniert: developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView nützlich, um sicherzustellen, dass das Element sichtbar ist

    – Juan Lanus

    25. Mai 2020 um 14:11 Uhr


Ich hatte das gleiche Problem vorher, ich bin mit der folgenden Funktion gelandet. Der erste Parameter ist für das zu überprüfende Element, der zweite ist, um zu überprüfen, ob das Element teilweise sichtbar ist. Es ist nur für die vertikale Überprüfung, Sie können es erweitern es, um nach horizontalem Scrollen zu suchen.

function checkInView(elem,partial)
{
    var container = $(".scrollable");
    var contHeight = container.height();
    var contTop = container.scrollTop();
    var contBottom = contTop + contHeight ;

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

    var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
    var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial ;

    return  isTotal  || isPart ;
}

überprüfe es jsFiddle .

  • Vielen Dank. Ich habe verschiedene Lösungen dafür gesehen, und dies ist die klarste und sauberste Methode, um dies zu erreichen. Vielen Dank!

    – Ronny

    1. Mai 2013 um 23:19 Uhr

  • schön zu hören, ich werde ein einfaches jquery-plugin dafür machen 🙂

    – Akram Berkawy

    2. Mai 2013 um 9:52 Uhr


  • Was ist, wenn der Container scrollbar ist und nicht angezeigt wird?

    – Aswin

    14. April 2020 um 1:20 Uhr

Benutzer-Avatar
Jonny Ngan

Basierend auf der besten Antwort. Anstatt Ihnen nur zu sagen, ob ein Element teilweise sichtbar ist oder nicht. Ich habe ein kleines Extra hinzugefügt, damit Sie einen Prozentsatz (0-100) eingeben können, der Ihnen sagt, ob das Element zu mehr als x % sichtbar ist.

function (container, element, partial) {
    var cTop = container.scrollTop;
    var cBottom = cTop + container.clientHeight;
    var eTop = element.offsetTop;
    var eBottom = eTop + element.clientHeight;
    var isTotal = (eTop >= cTop && eBottom <= cBottom);
    var isPartial;

    if (partial === true) {
        isPartial = (eTop < cTop && eBottom > cTop) || (eBottom > cBottom && eTop < cBottom);
    } else if(typeof partial === "number"){
        if (eTop < cTop && eBottom > cTop) {
            isPartial = ((eBottom - cTop) * 100) / element.clientHeight > partial;
        } else if (eBottom > cBottom && eTop < cBottom){ 
            isPartial = ((cBottom - eTop) * 100) / element.clientHeight > partial;
        }
    }
    return (isTotal || isPartial);
}

  • Dies ist auch jQuery-frei.

    – Rolf

    30. August 2017 um 10:48 Uhr


  • Ja, ich vermeide gerne jQuery

    – Jonny Ngan

    8. September 2017 um 10:11 Uhr

  • Von allen anderen scheint nur diese bei mir richtig zu funktionieren.

    – Austin Burk

    20. April 2021 um 20:34 Uhr

Ich konnte dies zum Laufen bringen, indem ich eine kleine Änderung an der geposteten reinen Javascript-Version vornahm

function checkInView(container, element, partial) {

    //Get container properties
    let cTop = container.scrollTop;
    let cBottom = cTop + container.clientHeight;

    //Get element properties
    let eTop = element.offsetTop - container.offsetTop; // change here
    let eBottom = eTop + element.clientHeight;

    //Check if in view    
    let isTotal = (eTop >= cTop && eBottom <= cBottom);
    let isPartial = partial && (
      (eTop < cTop && eBottom > cTop) ||
      (eBottom > cBottom && eTop < cBottom)
    );

    //Return outcome
    return  (isTotal  || isPartial);
  }

Hier ist eine reine Javascript-Lösung.

function elementIsVisible(element, container, partial) {
    var contHeight = container.offsetHeight,
    elemTop = offset(element).top - offset(container).top,
    elemBottom = elemTop + element.offsetHeight;
    return (elemTop >= 0 && elemBottom <= contHeight) || 
    (partial && ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= contHeight)))
}

// checks window
function isWindow( obj ) {
    return obj != null && obj === obj.window;
}

// returns corresponding window
function getWindow( elem ) {
    return isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
}

// taken from jquery
// @returns {{top: number, left: number}} 
function offset( elem ) {

    var docElem, win,
        box = { top: 0, left: 0 },
        doc = elem && elem.ownerDocument;

    docElem = doc.documentElement;

    if ( typeof elem.getBoundingClientRect !== typeof undefined ) {
        box = elem.getBoundingClientRect();
    }
    win = getWindow( doc );
    return {
        top: box.top + win.pageYOffset - docElem.clientTop,
        left: box.left + win.pageXOffset - docElem.clientLeft
    };
};

Benutzer-Avatar
Jony-Y

Habe für meine Zwecke damit herumgespielt. Hier ist meine Lösung (Vanille)

Menu ist der Container, el ist das aktive Element.

const isVisible = (menu, el) => {
      const menuHeight = menu.offsetHeight;
      const menuScrollOffset = menu.scrollTop;
    
      const elemTop = el.offsetTop - menu.offsetTop;
      const elemBottom = elemTop + el.offsetHeight;
      return (elemTop >= menuScrollOffset &&
     elemBottom <= menuScrollOffset + menuHeight);
    }

Benutzer-Avatar
Uigurisches Leben ist wichtig

Ich habe ein jquery-Plugin mit der letzten Antwort erstellt:

(function($) {
    $.fn.reallyVisible = function(opt) {

        var options = $.extend({
            cssChanges:[
                { name : 'visibility', states : ['hidden','visible'] }
            ],
            childrenClass:'mentioners2',
            partialview : true
        }, opt);

        var container = $(this);
        var contHeight;
        var contTop;
        var contBottom;
        var _this = this;
        var _children;

        this.checkInView = function(elem,partial){

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

            var isTotal = (elemTop >= 0 && elemBottom <=contHeight);
            var isPart = ((elemTop < 0 && elemBottom > 0 ) || (elemTop > 0 && elemTop <= container.height())) && partial ;

            return  isTotal  || isPart ;
        }

        this.bind('restoreProperties',function(){
            $.each(_children,function(i,elem){
                $.each(options.cssChanges,function(i,_property){
                    $(elem).css(_property.name,_property.states[1]);        
                });
            });
            _children = null;
        });

        return this.each(function(){
            contHeight = container.height();
            contTop = container.scrollTop();
            contBottom = contTop + contHeight ;

            _children = container.children("."+options.childrenClass);

            $.each(_children,function(i,elem){
                var res = _this.checkInView(elem,options.partialview);
                if(  !res ){
                    $.each(options.cssChanges,function(i,_property){
                        $(elem).css(_property.name,_property.states[0]);        
                    });
                }
            });

        }); 
    }

})(jQuery);

1113830cookie-checkErkennt, wenn Elemente innerhalb eines scrollbaren div-Elements nicht sichtbar sind

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy