How to Make a Sidebar Sticky When Scrolling Between Header and Footer with Jquery (Without Scrolling Over Them)

How to make a sidebar sticky when scrolling between header and footer with jQuery (without scrolling over them)?

EDIT - jquery solution (original css only answer below):

Based on your question edits that provide additional constraints and make an html / css only solution a bit more difficult, below is a jquery solution using your code with new jquery for the sticky sidebar widget and css to make the sidebar widget position: absolute and right: 30px (that value is arbitrary depending on where exactly you want the widget to sit inside the sidebar). Also, commented out a few other css lines that either weren't doing anything or interfered with the responsiveness of your grid layout (sticky sidebar functionality works with or without those changes, although you may need to adjust the right css of your widget element, including media queries, depending on where your layout ultimately ends up).

$(function() {
const sidebar = $('.sidebar-container');
const widget = $('.widget');
const footer = $('.footer');
const space = 10; // arbitrary value to create space between the window and widget
const startTop = sidebar.offset().top + 60; // arbitrary start top position
const endTop = footer.offset().top - widget.height() - space;
widget.css('top', startTop);
$(window).scroll(function() {
const windowTop = $(this).scrollTop();
const widgetTop = widget.offset().top;
let newTop = startTop;
if (widgetTop >= startTop && widgetTop <= endTop) {
if (windowTop > startTop - space && windowTop < endTop - space) {
newTop = windowTop + space;
} else if (windowTop > endTop - space) {
newTop = endTop;
}

widget.stop().animate({
'top': newTop
});
}
});
});
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');

* {
font-family: 'Open Sans';
color: #fff;
box-sizing: content-box;
}

body {
padding: 0;
margin: 0;
}

p {
margin: 20px;
}

hr {
width: 85%;
border-style: solid;
}

.main-content {
width: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 150px auto;
grid-template-areas: "nav nav nav nav" "main main main sidebar";
grid-column-gap: 20px;
grid-row-gap: 0px;
}

.nav {
grid-area: nav;
background-color: #266392;
display: grid;
grid-template-columns: 1fr 3fr 1fr;
}

.nav h1 {
place-self: center;
font-weight: 400;
font-size: 40px;
grid-column: 2;
}

.nav i {
align-self: center;
font-size: 40px;
}

.main {
height: 1500px;
/*width: 98%;
justify-self: start;*/
grid-area: main;
padding: 10px;
/*float: left;*/
background-color: #e8624c;
margin: 10px;
}

.sidebar-container {
height: 900px;
width: 300px;
justify-self: end;
background-color: #209B66;
grid-area: sidebar;
grid-column: 4;
/*top: 10px;*/
margin: 10px;
padding: 20px;
display: grid;
grid-template-rows: auto;
grid-row-gap: 10px;
}

.sidebar-container>p {
display: grid;
align-items: start;
padding: 0;
margin: 0;
}

.widget {
height: 500px;
width: 300px;
background-color: #E3962F;
position: absolute;
right: 30px;
}

.footer {
background-color: #333;
height: 800px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="main-content">
<div class="nav">
<h1>Sticky Sidebar Problem</h1>
<i class="fa fa-arrow-down" aria-hidden="true"></i>
</div>
<div class="main">
<p>
[Main Content]
</p>
</div>
<div class="sidebar-container">
<p>[Sidebar Container]</p>
<div class="widget">
<p> [Widget]</p>
</div>
</div>
</div>
<div class="footer"></div>
</body>

how to create Fixed Sidebar during Scrolling between Header and footer?

Try this. You have to take care of padding of your body because it's padding-top has to be more then or euqal to the height of your header and padding-left has to be more then the width of your sidebar. so that your content doesn't overlap with these two.

body{    padding:60px 0 0 150px;}.header { background: GREEN; color: #fff; position:fixed; width:100%; top:0; left:0; height:60px; z-index:100;}
.navbar-brand { padding: 0px;}
.navbar-brand>img { width: 250px; height: 51px; }
.navbar { margin-bottom: 0px !important;}
.navbar-nav>li>a { color: #fff !important; padding-bottom: 12px;}
.nav > li > a:hover, .nav > li > a:focus { text-decoration: none; /* background-color:#3385ff !important; */ color:#d83b01 !important; cursor:pointer;}
.icon-bar { background-color: white;}#wrap { min-height: 100%; height: auto; padding: 0 0 60px; }

.footer { background: green; color: #fff; height:70px; position: fixed; width:100%; padding-bottom: 100% auto; bottom:0; left:0;}
#custom-search-input{ padding: 3px; border: solid 1px #E4E4E4; border-radius: 6px; background-color: #fff;}
#custom-search-input input{ border: 0; box-shadow: none;}
#custom-search-input button{ margin: 2px 0 0 0; background: none; box-shadow: none; border: 0; color: #666666; padding: 0 8px 0 10px; border-left: solid 1px #ccc;}
#custom-search-input button:hover{ border: 0; box-shadow: none; border-left: solid 1px #ccc;}
#custom-search-input .glyphicon-search{ font-size: 23px;}.sidebar{ top: 0; left: 0; bottom: 0; overflow-y: auto; min-height: 600px; position:fixed; top:60px; left:0; width:130px; /* background-color: #f5f5f5; */ background: #fafafa none repeat scroll 0 0; padding:10px 5px; border:1px solid #DDDDDD;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div id="wrap"> <header>        <!-- Navigation -->        <nav class="navbar  header" role="navigation">            <div class="container">                <!-- Brand and toggle get grouped for better mobile display -->                <div class="navbar-header">     <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">      <span class="sr-only">Toggle navigation</span>      <span class="icon-bar"></span>      <span class="icon-bar"></span>      <span class="icon-bar"></span>     </button>                    <a class="navbar-brand" href="#/home">                        MYDEMO                    </a>                </div>                <!-- Collect the nav links, forms, and other content for toggling -->                                <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">                    <ul class="nav navbar-nav navbar-right">                        <li >                           <a id="login-button"                                role="button" data-toggle="modal" data-target="#login-modal" data-backdrop="static" data-controls-modal="login-modal" >  <i class="fa fa-sign-in"></i> </a>                                                   </li>                                                                  </ul>                </div>                <!-- /.navbar-collapse -->            </div>                        <!-- /.container -->        </nav>    </header>    <div class="row" style="margin-top:10px">        <div class="col-md-offset-3 col-md-6" >            <div id="custom-search-input">                <div class="input-group col-md-12">                    <input type="text" class="form-control input-lg" placeholder="Buscar" />                    <span class="input-group-btn">                        <button class="btn btn-info btn-lg" type="button">                            <i class="glyphicon glyphicon-search"></i>                        </button>                    </span>                </div>            </div>        </div>    </div><br>    <div class="container">    <div class="row">        <div class="col-md-3">            <div class="sidebar">                <section>                 <div class="filter-field">                    <legend>filters</legend>                    <div class="checkbox" >       <label><input type="checkbox" class="filter" value="">Option 1</label><br>       <label><input type="checkbox" class="filter" value="">Option 2</label><br>       <label><input type="checkbox" class="filter"  value="">Option 3</label><br>       <label><input type="checkbox" class="filter" value="">Option 4</label><br>        <label><input type="checkbox" class="filter" value="">Option 5</label><br>       <label><input type="checkbox" class="filter" value="">Option 6</label><br>       <label><input type="checkbox" class="filter"  value="">Option 7</label><br>       <label><input type="checkbox" class="filter" value="">Option 8</label><br>        <label><input type="checkbox" class="filter" value="">Option 9</label><br>       <label><input type="checkbox" class="filter" value="">Option 10</label><br>       <label><input type="checkbox" class="filter"  value="">Option 11</label><br>       <label><input type="checkbox" class="filter" value="">Option 12</label><br>     </div>                    </div>                </section>            </div>                    </div>        <div class="col-md-9">            <p>this is moveable content</p>             <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>             <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>             <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>                <p>this is moveable content</p>             <p>this is moveable content</p>              <p>this is moveable content</p>               <p>this is moveable content</p>                <p>this is moveable content</p>        </div>    </div>    </div>    </div><!--wrap--><div class="footer"></div>

Make scrolling sidebar stop at footer

You can check if you've scrolled down to the footer, then remove the stick class:

function sticky_relocate() {
var window_top = $(window).scrollTop();
var footer_top = $("#footer").offset().top;
var div_top = $('#sticky-anchor').offset().top;
var div_height = $("#sticky").height();

if (window_top + div_height > footer_top)
$('#sticky').removeClass('stick');
else if (window_top > div_top) {
$('#sticky').addClass('stick');
} else {
$('#sticky').removeClass('stick');
}
}

(you could combine the if to remove the duplicate .removeClass, here for demonstration)

However, with your css you get a nasty 'jump' around when you start scrolling - in your fiddle, the right content appears below #sticky then when you stick #sticky, the right content jumps to fill the gap. Using the code above, you'll get some race-conditions as the offset() moves when it fills/unfills the gap.

To fix this gap, just add a float:left to your #sticky css.

Updated fiddle: http://jsfiddle.net/0mLzseby/472/


I suspect you would like to go one step further and, when you get to the bottom, the div then starts to scroll with the page. You can do this by adjusting the 'position:fixed' top of .stick. Don't forget to reset it when not below the footer:

function sticky_relocate() {
var window_top = $(window).scrollTop();
var footer_top = $("#footer").offset().top;
var div_top = $('#sticky-anchor').offset().top;
var div_height = $("#sticky").height();

var padding = 20; // tweak here or get from margins etc

if (window_top + div_height > footer_top - padding)
$('#sticky').css({top: (window_top + div_height - footer_top + padding) * -1})
else if (window_top > div_top) {
$('#sticky').addClass('stick');
$('#sticky').css({top: 0})
} else {
$('#sticky').removeClass('stick');
}
}

The padding just makes it start scrolling in a more natural place - you can probably get this from other css attributes such as margin and padding of the other components.

Updated fiddle: http://jsfiddle.net/0mLzseby/473/

How do I stop a fixed sidebar from overlapping the footer with jQuery?

This correct answer was provided by benvc on this post. Sorry for the duplicate. I wanted to post the answer here in case anyone landed on this page rather than the other.

...below is a jquery solution using your code with new jquery for the sticky sidebar widget and css to make the sidebar widget position: absolute and right: 30px (that value is arbitrary depending on where exactly you want the widget to sit inside the sidebar). Also, commented out a few other css lines that either weren't doing anything or interfered with the responsiveness of your grid layout (sticky sidebar functionality works with or without those changes, although you may need to adjust the right css of your widget element, including media queries, depending on where your layout ultimately ends up).

$(function() {
const sidebar = $('.sidebar-container'); const widget = $('.widget'); const footer = $('.footer'); const space = 10; // arbitrary value to create space between the window and widget const startTop = sidebar.offset().top + 60; // arbitrary start top position const endTop = footer.offset().top - widget.height() - space; widget.css('top', startTop); $(window).scroll(function() { let windowTop = $(this).scrollTop(); let widgetTop = widget.offset().top; let newTop = startTop; if (widgetTop >= startTop && widgetTop <= endTop) { if (windowTop > startTop - space && windowTop < endTop - space) { newTop = windowTop + space; } else if (windowTop > endTop - space) { newTop = endTop; } widget.stop().animate({ 'top': newTop }); } }); });
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');* {  font-family: 'Open Sans';  color: #fff;  box-sizing: content-box;}
body { padding: 0; margin: 0;}
p { margin: 20px;}
hr { width: 85%; border-style: solid;}
.main-content { width: 100%; display: grid; grid-template-columns: repeat(4, 1fr); grid-template-rows: 150px auto; grid-template-areas: "nav nav nav nav" "main main main sidebar"; grid-column-gap: 20px; grid-row-gap: 0px;}
.nav { grid-area: nav; background-color: #266392; display: grid; grid-template-columns: 1fr 3fr 1fr;}
.nav h1 { place-self: center; font-weight: 400; font-size: 40px; grid-column: 2;}
.nav i { align-self: center; font-size: 40px;}
.main { height: 1500px; /*width: 98%; justify-self: start;*/ grid-area: main; padding: 10px; /*float: left;*/ background-color: #e8624c; margin: 10px;}
.sidebar-container { height: 900px; width: 300px; justify-self: end; background-color: #209B66; grid-area: sidebar; grid-column: 4; /*top: 10px;*/ margin: 10px; padding: 20px; display: grid; grid-template-rows: auto; grid-row-gap: 10px;}
.sidebar-container>p { display: grid; align-items: start; padding: 0; margin: 0;}
.widget { height: 500px; width: 300px; background-color: #E3962F; position: absolute; right: 30px;}
.footer { background-color: #333; height: 800px;}
<body>  <div class="main-content">    <div class="nav">      <h1>Sticky Sidebar Problem</h1>      <i class="fa fa-arrow-down" aria-hidden="true"></i>    </div>    <div class="main">      <p>        [Main Content]      </p>
</div> <div class="sidebar-container"> <p>[Sidebar Container]</p>
<div class="widget"> <p> [Widget]</p> </div> </div> </div> <div class="footer"></div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script></body>

Fixed Sidebar Scrolling and Stop at Footer

I have done some modification to your code so that the sidebar that is Faq session will stay below the header on scroll

$(window).scroll(function() {  if ($(window).scrollTop() > 150) {    $(".faqnav > div").css("position", "fixed");    $(".faqnav > div").css("top", "90px");  } else if ($(window).scrollTop() <= 0) {    $(".faqnav > div").css("position", "");    $(".faqnav > div").css("top", "");  }  if (    $(".faqnav > div").offset().top + $(".faqnav > div").height() >    $("#backup").offset().top  ) {
$(".faqnav > div").css("position", "sticky"); }});
.header {  width: 100%;  height: 90px;  background: #000;  position: fixed;  z-index: 99999;  top: 0;}.spud {  margin-top: 150px;}.faqs {  padding: 90px;      Padding-bottom: 15px;}.faqs > div {  display: flex;  flex-wrap: wrap;  width: 1200px;  margin: auto;}.faqs > div > div.faqnav {  width: 25%;}.faqs > div > div.faqnav > div {  padding: 0 30px 0 12px;}.faqs > div > div.faqnav > div a {  display: block;  padding: 10px 0;  position: relative;  color: #999;  -webkit-transition: all 0.25s linear;  -moz-transition: all 0.25s linear;  -ms-transition: all 0.25s linear;  -o-transition: all 0.25s linear;  transition: all 0.25s linear;}.faqs > div > div.faqnav > div a.heyo {  color: #2880f8;}.faqs > div > div.faqnav > div a:before {  content: "";  width: 3px;  height: 25px;  display: inline-block;  line-height: 45px;  position: absolute;  background: #999;  left: -10px;}.faqs > div > div.faqnav > div a.heyo:before {  background: #2880f8;}.faqs > div > div.faqnav > div a.heyo:focus:before {}.faqs > div > div.faqwrap {  width: 75%;}p.toggle {  color: #666;  cursor: pointer;  width: 100%;  text-align: left;  border: none;  outline: none;  transition: 0.4s;  margin: 0 0 10px;}p.toggle:before {  content: "\f105";  font-family: FontAwesome;  margin-right: 10px;  display: inline-block;  font-size: 14px;  color: #2880f8;  top: 0;  position: relative;  transition: 0.4s;}p.toggle.active {  color: #2880f8;}p.toggle.active:before {  content: "\f107";}.accordion {  height: 500px;}.accordion:focus {  outline: none;}.accordion .inner {  padding: 0 20px 20px;  overflow: hidden;  display: none;}.accordion .inner ol,.accordion .inner ul {  padding-left: 0;}.accordion:first-child {  background: #fafafa;  margin-bottom: 20px;}.accordion:nth-child(2) {  background: #fafafa;  margin-bottom: 20px;}.accordion:nth-child(3) {  background: #fafafa;}.accordion > div {  padding: 50px;}.accordion > div h3 {  color: #666;  font-weight: bold;}#backup {  background: #000;  height: 800px;  width: 100%;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script><header class="header">NAV</header><section class="spud">  <h1>FAQs</h1></section><section class="faqs">  <div>    <div class="faqnav">      <div>        <a href="#one" class="heyo">One</a>        <a href="#two">Two</a>        <a href="#three">Three</a>      </div>    </div>    <div class="faqwrap">      <div class="accordion" id="one">        <div>          <h3>One </h3>        </div>      </div>      <div class="accordion" id="two">        <div>          <h3>Two</h3>        </div>      </div>      <div class="accordion" id="three">        <div>          <h3>Three</h3>        </div>      </div>    </div>  </div>
</section><div id="backup"></div>

On-scroll fixed sidebar overlapping on footer

you can do that with pure Css without using JavaScript :

`
.container{
position:relative;
}
#aside-content{
position: sticky;
top: 0;
align-self: flex-start;
}
`


Related Topics



Leave a reply



Submit