nsilva
nsilva

Reputation: 5622

jQuery - Make an element stay in position once it is scrolled past a certain point

I have the following code:-

HTML

<div id="header"></div>
<div id="content">
    <div class="sidebar-wrapper"></div>
</div>
<div class="sessions-wrapper"></div>
<div id="footer"></div>

CSS

#header {
  height: 600px;
  width: 100%;
  background: black;
}
#content {
  height: 2000px;
  width: 100%;
  background: #eeeeee;
}

.sidebar-wrapper {
    width: 100%;
    height: 350px; /*depends on content*/
    background: rgba(0,0,0,0.2);
    border-radius: 20px;
    padding: 20px;
    margin-top: 50px;
}

.sessions-wrapper {
  height: 200px;
  width: 100%;
  background: #000000;
}

#footer {
  width: 100%;
  height: 500px;
  background: #888;
}

jQuery

jQuery.fn.scrollBottom = function() {
    return jQuery(document).height() - this.scrollTop() - this.height();
};

var sidebar = jQuery('.sidebar-wrapper');
var pwindow = jQuery(window);
var sessions = jQuery('.sessions-wrapper');
var sidebar_gap = sidebar.offset().top;

pwindow.bind("scroll resize", function() {
    var gap = pwindow.height() - sidebar.height() - 10;
    var sessions_gap = sessions.offset().top - sidebar.offset().top;
    var visibleFoot = 172 - pwindow.scrollBottom();
    var scrollTop = pwindow.scrollTop()

    if(scrollTop > sidebar_gap - 140 && sessions_gap > 750 && visibleFoot < -850) {
        sidebar.css({
            'position': 'fixed',
            'top': '100px',
            'width': '100%'
        });
    } else if (sessions_gap < 750 && visibleFoot > -850) {
        sidebar.css({
            'position': 'static',
            'top': '0px',
            'width': '100%'
        });
    } else {
        sidebar.css({
            'position': 'static',
            'top': '0px',
            'width': '100%'
        });
    }
});

VIEW JSFIDDLE

At the moment the sidebar-wrapper scrolls down the page as you go down the page until it reaches the bottom. Instead of sidebar-wrapper going back to it's original position when at the bottom I want to be able to have this element remain at the position it disappears and then scroll as you go back up the page.

I'm doing it this way as this function it to work across different pages with the same elements but different content (so the heights of the elements would be different on each page)

Thanks in advance, if I have been unclear, please let me know.

Upvotes: 1

Views: 668

Answers (2)

Dacklf
Dacklf

Reputation: 700

I think this script accomplishes what you ask for:

<script type='text/javascript'>
  jQuery.fn.scrollBottom = function() {
    console.log('scrollBottom');
    return jQuery(document).height() - this.scrollTop() - this.height();
};

var sidebar = jQuery('.sidebar-wrapper');
var pwindow = jQuery(window);
var sessions = jQuery('.sessions-wrapper');
var sidebar_gap = sidebar.offset().top;

var content = $('#content');

// original sidebar position
var original_sidebar_top = sidebar.position().top;    
var desired_offset = 140;
var separation = 20;

pwindow.bind('scroll resize', function() {
    // sidebar & header height
    var sb_height = sidebar.height();        
    var header_height = $('#header').height();
    var scrollTop = pwindow.scrollTop();        

    // compute the real offset in screen (not the document)
    var screen_offset_ss = sessions.offset().top - scrollTop;        
    var distance = desired_offset+sb_height+separation;

    // there's space for the sidebar
    if (distance < screen_offset_ss) {
        // header is not showing, fix sidebar position
        if (scrollTop > header_height-desired_offset) {
            console.log('fixed');
            sidebar.css({
                'position': 'fixed',
                'top': desired_offset+'px'
            });
        }
        // header is showing, return sidebar to original position
        else {
            console.log('static');
            sidebar.css({
                'position': 'static',
                'top': original_sidebar_top+'px'
            });                
        }
    }

    // there's no space for the sidebar
    else {
        console.log('20px');
        sidebar.css({
            'position': 'relative',                
            // place the sidebar right above the sessions (with separation)
            'top': sessions.offset().top - content.position().top - sb_height - separation
        });
    }
});
</script>

Here's a JSFiddle.

Please, note the change I made in the CSS. It was causing an issue (blinking).

.sidebar-wrapper {
    width: 100%;
    height: 350px; /*depends on content*/
    background: rgba(0,0,0,0.2);
    border-radius: 20px;
    /*padding: 20px;         commented*/
    /*margin-top: 50px;      commented*/
}

If you still want the margin, better put it as margin-bottom:50px; in the #content

Upvotes: 1

Julien
Julien

Reputation: 2756

Try this :

    if(scrollTop > 500 && sessions_gap > 750 && visibleFoot < -850) {
        sidebar.css({
            'position': 'fixed',
            'top': '100px',
            'width': '100%'
        });
    } else if (scrollTop > 500 && sessions_gap > 750 && visibleFoot >= -850) {
        sidebar.css({
            'position': 'relative',
            'top': (gap+700)+'px',
            'width': '100%'
        });
    } else {
        sidebar.css({
            'position': 'static',
            'top': '0px',
            'width': '100%'
        });
    }

I don't know why but the div blinks on JSFiddle, I don't know if it will do the same on elsewhere.

Upvotes: 0

Related Questions