Ace Goulet

jQuery + CSS3 Scrolling Effects and Transitions Without Heavy Plugins

In a site I built recently, I had the need to have scrolling effects and transitions on various elements, but I didn’t want to use heavy plugins and I wanted the transitions to work when the page was scrolled either up or down. Since the site was already using jQuery, that was my javascript poison pick.

First I came up with this one, which fades out elements as you scroll down the page and fades them back in when you scroll back up:

function scrollfade(element, range, manualoffset){
    function scrollfade(element, range, manualoffset){ 
        $(window).on('scroll', function () {
        var scrollTop = $(this).scrollTop();
        var offset = element.offset().top;
        if(manualoffset !== 0){
            offset = manualoffset;
        }
        var height = element.outerHeight();
        offset = offset + height / 2;
        var calc = 1 - (scrollTop - offset + range) / range;
        element.css({ 'opacity': calc });
        if ( calc > '1' ) {
            element.css({ 'opacity': 1 });
        } else if ( calc < '0' ) {
            element.css({ 'opacity': 0 });
        }
    });
}

Usage:

scrollfade($('.header-logo'), 20, 0);

Once I had that working the way I wanted, I created the reverse function, which fades elements in when scrolling down the page, and out when scrolling back up:

function scrollfade_in(element, range, manualoffset, emthreshold){
    if($(window).height() < 450){
        manualoffset = manualoffset / 4;
    }
    $(window).scroll(function() {
        $(element).each(function(){
            var scrollTop = $(window).scrollTop(); 
            var offset = $(this).offset().top; 
            var height = $(this).outerHeight();
            var window_height = $(window).outerHeight(); 
            var window_offset_bottom = window_height - manualoffset; 
            var window_offset_top = window_height - manualoffset - range; 
            var calc = 1 + (scrollTop - offset + window_offset_bottom) / range;
            $(this).css({ 'opacity': calc });
            if ( calc > '1' ) {
                $(this).css({ 'opacity': 1 });
            } else if ( calc < '0' ) {
                $(this).css({ 'opacity': 0 });
            }
        });
    }).scroll();
}

Useage:

scrollfade_in($('.fade-in-out-scroll-simple'), 100, 300);

Then I thought to myself, “hey it would also be cool if something could fade in and also slide up a little bit” so I made a function for that too:

function scrollfade_in_up(element, range, manualoffset, emthreshold){
    if($(window).height() < 450){
        manualoffset = manualoffset / 4;
    }
    $(window).scroll(function() {
        $(element).each(function(){
            var scrollTop = $(window).scrollTop(); 
            var offset = $(this).offset().top; 
            var height = $(this).outerHeight(); 
            var window_height = $(window).outerHeight(); 
            var window_offset_bottom = window_height - manualoffset; 
            var window_offset_top = window_height - manualoffset - range; 
            var calc = 1 + (scrollTop - offset + window_offset_bottom) / range;
            top_calc = emthreshold - calc;
            $(this).css({ 'opacity': calc });
            $(this).css({ 'top': top_calc + 'rem' });
            if ( calc > '1' ) {
                $(this).css({ 'opacity': 1 });
            } else if ( calc < '0' ) {
                $(this).css({ 'opacity': 0 });
            }
            if ( top_calc >= emthreshold ) {
                $(this).css({ 'top': emthreshold +'rem' });
            } else if ( top_calc < '0' ) {
                $(this).css({ 'top': 0 });
            }
        });
    }).scroll();
}

Usage:

scrollfade_in_up($('.fade-in-out-scroll'), 100, 300, 2.5);

Then I was like “Whoa that’s cool, let’s make things that can slide in from the left and right!”

function scrollfade_in_left(element, range, manualoffset, emthreshold){
    if($(window).height() < 450){ 
        manualoffset = manualoffset / 4; 
    }
    $(window).scroll(function() {
        $(element).each(function(){ 
            var scrollTop = $(window).scrollTop(); 
            var offset = $(this).offset().top; 
            var height = $(this).outerHeight(); 
            var window_height = $(window).outerHeight(); 
            var window_offset_bottom = window_height - manualoffset; 
            var window_offset_top = window_height - manualoffset - range; 
            var calc = 1 + (scrollTop - offset + window_offset_bottom) / range; 
            left_calc = emthreshold - calc; 
            $(this).css({ 'opacity': calc }); 
            $(this).css({ 'transform': 'translateX('+-left_calc+'rem)' }); 
            if ( calc > '1' ) {
                $(this).css({ 'opacity': 1 });
            } else if ( calc < '0' ) { 
                $(this).css({ 'opacity': 0 }); 
            } 
            if ( left_calc >= emthreshold ) {
                $(this).css({ 'transform': 'translateX('+-emthreshold+'rem)' });
            } else if ( left_calc < '0' ) {
                $(this).css({ 'transform': 'translateX(0)' });
            }
        });
    }).scroll();
}

function scrollfade_in_right(element, range, manualoffset, emthreshold){
    if($(window).height() < 450){ 
        manualoffset = manualoffset / 4; 
    } 
    $(window).scroll(function() { 
        $(element).each(function(){ 
            var scrollTop = $(window).scrollTop(); 
            var offset = $(this).offset().top; 
            var height = $(this).outerHeight(); 
            var window_height = $(window).outerHeight(); 
            var window_offset_bottom = window_height - manualoffset; 
            var window_offset_top = window_height - manualoffset - range; 
            var calc = 1 + (scrollTop - offset + window_offset_bottom) / range; 
            left_calc = emthreshold - calc; 
            $(this).css({ 'opacity': calc }); 
            $(this).css({ 'transform': 'translateX('+left_calc+'rem)' }); 
            if ( calc > '1' ) {
                $(this).css({ 'opacity': 1 });
            } else if ( calc < '0' ) { 
                $(this).css({ 'opacity': 0 }); 
            } 
            if ( left_calc >= emthreshold ) {
                $(this).css({ 'transform': 'translateX('+emthreshold+'rem)' });
            } else if ( left_calc < '0' ) {
                $(this).css({ 'transform': 'translateX(0)' });
            }
        });
    }).scroll();
}

Usage:

scrollfade_in_left($('.fade-in-out-scroll-left'), 100, 300, 2.5);
scrollfade_in_right($('.fade-in-out-scroll-right'), 100, 300, 2.5);

Then to finish things up, I added a couple lines of css to the classes used for the transitions:

.fade-in-out-scroll, 
.fade-in-out-scroll-left, 
.fade-in-out-scroll-right {
    opacity: 0;
    position: relative;
}

Depending on your project, the design, intended devices, etc, you’ll want to play around with the ‘range’, ‘manualoffset’ and ’emthreshold’ values in order to make sure your transitions are firing and ending exactly where you want them to. I also ended up adding in some additional css to disable the transitions on certain mobile device sizes for reliability, but that’s really on a case by cases basis so I didn’t include it.

No go forth and transition!

Exit mobile version