2

I got a scrollable page containing a lot of divs. I want to fade out the elements at the top and bottom of the page while the user is scrolling; so only the divs which are currently in the center of the viewport will have an opacity of 100%.

divs with opacity depending on their position

I am currently achieving this by observing the window.scroll event and calculating each divs opacity by their position in relation to the scroll offsets. This works, but has an huge impact on the clients performance (specially when there are a lot of divs) - which leads to a "non fluid" scrolling experience.

Are there other approaches available? Maybe even a solution without going through every single div?


Edit:

  1. I setup a quick preview on jsFiddle, which illustrates my current approach (not optimized)
  2. Thanks for you comments! I really like the idea of using a background gradient to fake the elements opacity - but in my case this won't work, because I got an background image.
RienNeVaPlu͢s
  • 7,442
  • 6
  • 43
  • 77
  • 2
    Your code would somewhat help – Sven Bieder Jun 03 '13 at 15:44
  • I'm not sure that there is a better approach. That sounds like exactly how I would do it too. I don't think the performance issues are with going through each div, but with the graphics chipset of the client struggling to constantly redraw the page. – crush Jun 03 '13 at 15:46
  • 1
    One thing you could do is have a gradient background, and not change the transparency on the divs. That way as they scroll, the background makes them appear to disappear. – crush Jun 03 '13 at 15:50
  • 1
    Make sure you only perform the calculations on the divs that are in the actual viewport of the browser. – Hendrik Jun 03 '13 at 16:03
  • thanks so far guys, I updated the question with an example – RienNeVaPlu͢s Jun 03 '13 at 16:21

1 Answers1

3

Example on jsFiddle

// http://stackoverflow.com/a/488073/340760
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));
}

// when you scroll the div
$(".list").scroll(function(e) {
    var $list = $(this);

    // apply logic only to visible elements
    $list.find("div")
        .filter(function(i, d) {
            return isScrolledIntoView(d);
        })
        .each(function() {
            var eTop = $(this).offset().top;
            var center = $list.height() / 2;

            // if the element is in the center it is 100%
            // otherwise it will fade
            var dif = center - eTop;
            if (dif < 0) dif *= -1;

            var pc = 1 - (dif / center);

            // set the opacity for the elements
            $(this).css("opacity", pc);
        });
});
BrunoLM
  • 97,872
  • 84
  • 296
  • 452