Domanda

What I am trying to achieve:

  • When the top of an image reaches the top of window (by scrolling), a class "sticky" is added to the element
  • When that image that is now sticky reaches the bottom of its container, the class is removed and the element stays at that last bottom position
  • When a user moves back up, the same process happens, only starting from the bottom, going to the top.

Fiddle.

Relevant jQuery:

$(".entry-thumbnail").each(function () {
    var $this = $(this),
        p = $this.parent(),
        scrollT = $this.scrollTop(),
        scrollW = $(window).scrollTop(),
        scrollPT = p.scrollTop() + p.outerHeight();

    if (!$this.hasClass("sticky")) {
        console.log("Tada!");
        $(window).scroll(function () {
            if (scrollT <= scrollW) {
                $this.addClass("sticky");
            }
        });
    }
    else {
       $(window).scroll(function () {
            if (scrollT + $this.outerHeight() >= scrollPT) {
                $this.removeClass("sticky");
            }
        });
    }
});

Problems that I encounter:

  • Class is added to all elements
  • Elements position (left/right) changes when adding the class
  • Class doesn't get removed
È stato utile?

Soluzione

I took a different approach to your problem. I calculate the absolute height required inside the window.scroll event handler and then set the height to the appropriate article based on the scroll height.

Check the demo http://jsfiddle.net/eh3sT/ and let me know if it works for you.

Edit: You did fix most part of the issue yourself. Thanks :)

I don't think there is much to optimize, but I just modified a little to improve the readability. Check the full demo at http://jsfiddle.net/eh3sT/3/embedded/result/

Full Code:

var etPos = []
var $articles = $("article");
$articles.each(function () {
    var tPos = $(this).offset();
    etPos.push([tPos.top, tPos.top + $(this).height(), $(this).find('.entry-thumbnail').height()]);
});

$(window).scroll(function () {
    var scrollHeight = $(document).scrollTop();
    var cssProp = {};
    for (var i = 0; i < etPos.length; i++) {
        var $atricle = $articles.eq(i);
        if (scrollHeight >= (etPos[i][0]) && scrollHeight <= (etPos[i][1] - etPos[i][2] - 20)) {
            cssProp.top = scrollHeight - etPos[i][0] + 10;
            cssProp.bottome = "auto";
        } else if (scrollHeight > (etPos[i][1] - etPos[i][2] - 20) && $atricle.height() > ($atricle.find('.entry-thumbnail').height() + 10)) {
            /*
            Remove the second condition if the article height is always > respective thumbnail + 10. we don't want set bottom 10, if the thumbnail has no space to scroll.
            */
             cssProp.top = "auto";
             cssProp.bottom = 10;
        }else {
            cssProp.top = 10;
            cssProp.bottom = "auto";
        }
        $atricle.find('.entry-thumbnail').css(cssProp);
    }
});

Notes: Added article class to all article tags.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top