9

Hi I want to bind the the CSS opacity of two divs with how much that element is scrolled.

For example say I have two divs:

<div class="red" style="background:red"></div>
<div class="blue" style="background:blue"></div>

As the red div comes into the viewport, its opacity goes from 0 to 100 - depending on the amount scrolled.

Likewise as the blue div comes into viewport its opacity goes from 100 to 0, depending on the amount scrolled.

I found this Jquery/Javascript Opacity animation with scroll -

    var fadeStart=100 // 100px scroll or less will equiv to 1 opacity
    ,fadeUntil=200 // 200px scroll or more will equiv to 0 opacity
    ,fading = $('#fading')
;

$(window).bind('scroll', function(){
    var offset = $(document).scrollTop()
        ,opacity=0
    ;
    if( offset<=fadeStart ){
        opacity=1;
    }else if( offset<=fadeUntil ){
        opacity=1-offset/fadeUntil;
    }
    fading.css('opacity',opacity).html(opacity);
});

however the scroll amount is bound the document height, rather than the div itself.

Here is a jsfiddle to work from http://jsfiddle.net/RPmw9/

Thanks in advance.

1
  • Because offset = $(document).scrollTop() and not your element. I need to look into scrollTop property to see whether it is available to all elements. Commented Feb 14, 2014 at 5:55

1 Answer 1

11

Depends on when you want it fully opaque or not, but this could be a start:

»»Fiddle«« (Multiple element class version - set individually)

»»Fiddle«« (Single element class version - if only one element per class)

function fader() {
    var r = $('.red'),   // The .red DIV, as variable so we do not have to look
                         // it up multiple times.
        b = $('.blue'),  // Same for blue.
        wh = $(window).height(),      // Height of window (visible part).
        dt = $(document).scrollTop(), // Pixels document is scrolled down.
        /* red offset top is a semi static values which say how many pixels it
         * is from the top of the document.
         * "Red Offset Top" - "Document Scroll Top" gives us how many pixels
         * the red DIV is from top of visible window.
         * "Window Height" - that value gives us pixels the red DIV is from top
         * normalized to start from 0 when top of DIV is at bottom of window.
         * */
        redView  = wh - (r.offset().top - dt),
        // Same for blue DIV
        blueView = wh - (b.offset().top - dt),
        // Variable to save opacity value.
        op;
    /* If redView is bigger then 0 it means the DIV has top border above bottom
     * of window. 
     */
    if (redView > 0) {
        /* Opacity goes from 0 - 1 so we divide 1 by window height and
         * multiplies it with pixels red DIV is from bottom.
         * In addition we add the height of the red DIV to window height, such
         * that we set opacity until it is out of view (Bottom border is at top
         * of window, and not only until it has top border at top of window.)
         */
        op = 1 / (wh + r.height()) * redView;
        /* If value of calulation is less or equal to one, it is in visible
         * view and we set the opacity accordingly.
         */
        if (op <= 1)
            r.css('opacity', op);
    }
    if (blueView > 0) {
        op = 1 - 1 / (wh + b.height()) * blueView;
        if (op >= 0)
            b.css('opacity', op);
    }

    // Add this line for a possible help in understanding:
    console.log(
         'Window Height:', wh, 
         'Doc Scroll Top', dt, 
         'Red offset top:', r.offset().top, 
         'Red offs.top - Doc Scroll Top', r.offset().top - dt, 
         'View:', wh - (r.offset().top - dt)
    );
}
// Attach scroll event to the function fader()
$(document).bind('scroll', fader);

OK. Added some comments. Might not feel it is the best explanation. A better way to understand it is perhaps to have a look at the values so I also added a console.log() line inside the fader() function. Open your console and view the values as you scroll. Fiddle with logging. Also note this performance difference. style is considerably faster.

Version two:

This set full opacity when element has top at top of window, (not bottom of element). Note that we could use the Math.min() in the above function as well, to omit the op variable and if (op <= 1) and if (op >= 0) statement, but not at least a quick benchmark on jsperf revealed the if version to perform slightly better. If you have many elements that you style one should use the if version.

»»Fiddle««

function fader() {
    var r = $('.red'),
        b = $('.blue'),
        wh = $(window).height(),
        dt = $(document).scrollTop(),
        redView  = wh - (r.offset().top - dt),
        blueView = wh - (b.offset().top - dt);
    if (redView > 0) {
        // Math.min() returns the lowest of given values. Here we do not want
        // values above 1.
        $('.red').css('opacity', Math.min(1 / wh * redView, 1));
    }
    if (blueView > 0) {
        $('.blue').css('opacity', 1 - Math.min(1 / wh * blueView, 1));
    }
}
// Event on scroll
$(document).bind('scroll', fader);
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks so much! This is perfect! If you wouldn't mind could you explain the JavaScript a little so I can better understand how it works? Thanks so much though!!
@user3143218: OK. Added some comments. Not sure if it is understandable. Also added a line with console.log() which hopefully helps in understanding what is going on.
Thanks so much! Really comprehensive answer;) I had one issue, when I add multiple Blue and Red divs in the one page, it doesn't work properly. The console is error free tho :(
@user3143218: Yes, if you add multiple one way to go is to use unique ID's for each DIV instead of class. Else one could add a loop for the class as well. Here is an example looping all and setting individually: Fiddle
@user3143218: Err. That was not good. I'll see if I get time to look at it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.