I am trying to create a sidebar that functions like the one on Vice.com. If you scroll down, the sidebar will become fixed at a certain point, and then when the sidebar reaches a certain point near the bottom of the site, it will then continue to scroll up with the rest of the site.
On my site, I am stuck on the second part which is getting the sidebar to continue scrolling up once it hits near the bottom. 290px
from the bottom to be exact.
Here is what I have so far:
JavaScript
<script>
jQuery(window).scroll(function () {
var threshold = 20;
if (jQuery(window).scrollTop() >= 20)
jQuery('#sidebar').addClass('fixed');
else
jQuery('#sidebar').removeClass('fixed');
});
</script>
CSS
#sidebar {
margin: 0;
position: absolute;
right: 0;
width: 220px;
}
#sidebar.fixed {
margin-left: 720px;
position:fixed;
right: auto;
top: 173px;
}
How can I make the fixed sidebar scroll up once it hits a certain point near the bottom?
Edit #1
Here is the updated code by Adam. I'm using a conditional statement for the pages that have a different threshold. Nothing happens when I use this code, meaning the sidebar doesn't get the fixed
class added and therefore scrolls up normally as if the code isn't even there. Also, I get a console error on this line if (scrollTop() >= 236) {
saying that the "number is not a function".
if (jQuery(document.body).hasClass("home")) {
jQuery(window).scroll(function () {
var sidebarHeight = jQuery('#sidebar').height(),
containerHeight = jQuery('#container').height() + 173,
scrollTop = jQuery(window).scrollTop(),
clientHeight = scrollTop + jQuery(window).height(),
threshold = 654;
if (scrollTop() >= 654) {
jQuery('#sidebar').addClass('fixed');
} else if (containerHeight - scrollTop <= sidebarHeight) {
jQuery('#sidebar').removeClass('fixed').addClass('bottom');
}
});
} else if (jQuery(document.body).hasClass("single") || jQuery(document.body).hasClass("page")) {
jQuery(window).scroll(function () {
var sidebarHeight = jQuery('#sidebar').height(),
containerHeight = jQuery('#container').height() + 173,
scrollTop = jQuery(window).scrollTop(),
clientHeight = scrollTop + jQuery(window).height(),
threshold = 20;
if (scrollTop() >= 20) {
jQuery('#sidebar').addClass('fixed');
} else if (containerHeight - scrollTop <= sidebarHeight) {
jQuery('#sidebar').removeClass('fixed').addClass('bottom');
}
});
} else {
jQuery(window).scroll(function () {
var sidebarHeight = jQuery('#sidebar').height(),
containerHeight = jQuery('#container').height() + 173,
scrollTop = jQuery(window).scrollTop(),
clientHeight = scrollTop + jQuery(window).height(),
threshold = 236;
if (scrollTop() >= 236) {
jQuery('#sidebar').addClass('fixed');
} else if (containerHeight - scrollTop <= sidebarHeight) {
jQuery('#sidebar').removeClass('fixed').addClass('bottom');
}
});
}
Below is the HTML structure as requested:
<!-- BEGIN #masthead-->
<div id="masthead">
<!-- #secondary-menu -->
<div id="secondary-menu">
<!-- .centered-menu -->
<div class="centered-menu">
<div class="latest-tweets"></div>
<div id="search-bar"></div>
<ul class="social-icons sf-js-enabled"></ul>
</div>
<!-- /.centered-menu -->
</div>
<!-- /#secondary-menu -->
<!-- BEGIN #header-->
<div id="header">
<!-- #header-inner -->
<div id="header-inner" class="clearfix">
<div id="logo"></div>
<!-- BEGIN #primary-menu -->
<div id="primary-menu" class="clearfix">
<!-- .left-menu -->
<div class="left-menu split-menu"></div>
<!-- /.left-menu -->
<!-- .right-menu -->
<div class="right-menu split-menu">
<div class="menu-menu-right-container"></div>
<!-- /.right-menu -->
<!-- END #primary-menu -->
</div>
</div>
<!-- /#header-inner -->
<!-- END #header -->
<!-- BEGIN #mobile-menu -->
<div id="mobile-menu">
<div id="mobile-inner"></div>
</div>
<!-- END #mobile-menu -->
</div>
<div id="categories-bar"></div>
</div>
<div id="masthead-space"></div>
<!-- END #masthead -->
<!-- BEGIN #wrapper-->
<div id="wrapper">
<!-- BEGIN #page-->
<div id="page">
<div id="main" class="clearfix">
<div id="container" class="clearfix">
<!--BEGIN #content -->
<div id="content">
<div id="sidebar"></div><!-- #sidebar -->
</div>
</div>
<!--END #main -->
</div>
<!--END #page -->
</div>
<!--END #wrapper -->
</div>
<!--BEGIN #bottom -->
<div id="bottom">
<!--BEGIN #footer -->
<div id="footer"></div>
</div>
My advise:
Create 2 CSS classes with the characteristics you want and toggle both after reaching the break point, 1 must be active at the begining.
JS
var changePoint = $('#reaching_the_top_of_this_element_activates_change').offset().top;
$(window).scroll(function () {
if ($(window).scrollTop() >= changePoint) {
$('#sidebar').removeClass('blackStatic');
$('#sidebar').addClass('redFixed');
}
else {
$('#sidebar').addClass('blackStatic');
$('#sidebar').removeClass('redFixed');
}
});
CSS
.blackStatic {
position: static;
background-color: black;
color: red;
}
.redFixed {
position: fixed;
top: 0;
background-color: red;
color: black;
}