Home > Mobile >  Make sticky sidebar stop scrolling when it reaches the footer
Make sticky sidebar stop scrolling when it reaches the footer

Time:10-11

I've created a sticky sidebar for my blog, but now I need the sticky element to stop scrolling when I reach the footer. The reason is because the sidebar is overlapping the elements in the footer. How can I solve this?

Working fiddle with overlapping problem:

https://jsfiddle.net/j7x5hLy3/

This is EXACTLY what I'm trying to achieve:

https://abouolia.github.io/sticky-sidebar/examples/basic.html

Look what happens when the sidebar reaches the bottom. I AM NOT TRYING TO USE Z-INDEX. I'm saying this because in some other questions people are posting "solutions" that uses z-index. I'm not trying to hide anything, I'm trying to make it stop scrolling when it reaches the footer.

jQuery(document).ready(function($) {
    
  function isScrolledTo(elem) {
    var docViewTop = $(window).scrollTop(); //num of pixels hidden above current screen
    var docViewBottom = docViewTop   $(window).height();
    var elemTop = $(elem).offset().top; //num of pixels above the elem
    var elemBottom = elemTop   $(elem).height();

    return ((elemTop <= docViewTop));
  }

  var catcher = $('#bannernormal');
  var sticky = $('#bannerfixo');

  if ($(window).width() >= 100) {               
    $(window).scroll(function() {
      if (isScrolledTo(sticky)) {
        sticky.css('position', 'fixed');
        sticky.css('top', '0px');
      } 
      var stopHeight = catcher.offset().top   catcher.height();
      if (stopHeight > sticky.offset().top) {
        sticky.css('position', 'absolute');
        sticky.css('top', stopHeight);
      }
    });
        
  } else {
    $(window).unbind('scroll');
  }
});
#bannernormal {
  margin: auto;
  display: table;
  width: 200px;
  height: 400px;
  border: 1px solid #000;
  margin: 5px;
}

#bannerfixo {
  margin: 5px;
  width: 200px;
  height: 400px;
  border: 1px solid #000;
  margin: 5px;
}

#sidebar {
  float: left;
}

#content {
  float: right;
}

#footer {
  display: block;
  clear: both;
}
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>

<div id="content">
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
  Content <br><br><br><br><br><br><br><br>
</div>

<div id="sidebar">
  <div id="bannernormal">
    This is the "catcher" <code>div</code>
  </div>
  <div id="bannerfixo" style="position: absolute; top: 413px;">
    This is the "sticky" <code>div</code>
  </div>
</div>

<div id="footer">Everything should stop before this part.

  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>
  1010101010101011010<br/>

</div>

CodePudding user response:

In an effort to keep it simple, here are three nested divs. The root div represents the root of you document (usually <body) The content can be any div, as long as it has position: relative

The div <div id="relativeTop"> should have position: absolute. relativeTop will now position itself inside the parent, but you can position it explicitly using top, right, bottom and left. If the parent is not relative, it's children will be free to leave it's bounds and therefor will position it's children relative to the window instead.

In javascript, I listen to the scroll event

document.addEventListener('scroll', (e) => {

This is were you can set the top or bottom value. Look at the check:

if (window.scrollY   rect.height > parentRect.height) {

If true, you'll know the div would en up outside of the parent, and you can set top: 0px to have it stick to the bottom of it's parent.

Otherwise, you set the top value to the scroll position of the document:

el.style.top = window.scrollY   "px";

document.addEventListener('scroll', (e) => {
  const el = document.getElementById("relativeTop");
  const parent = el.parentNode;
  
  const parentRect = parent.getBoundingClientRect();
  const rect = el.getBoundingClientRect();
  
  if (window.scrollY   rect.height > parentRect.height) {
    el.style.bottom = "0px";
  } else {
    el.style.top = window.scrollY   "px";
  }
});
#body {
  border: 1px dotted yellow;
  height: 1500px;
}
#content {
  position: relative;
  border: 1px dotted red;
  height: 1000px;
  margin: 10px;
  width: 2000px;
}
#relativeTop {
  border: 1px dotted blue;
  position: absolute;
  left: 0;
  width: 200px;
  height: 100px;
}
<div id="body">
  <div id="content">
    <div id="relativeTop">
    </div>
  </div>
</div>

CodePudding user response:

.container {
  display: flex;
  margin-bottom: 10px;
}

.section {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
}

.sidebar {
  width: 180px;
  height: 160px;
  background: green;
  margin-right: 10px;
}

.normal {
  background: yellow;
  margin-bottom: 10px;
}

.sticky {
  background: red;
  position: sticky;
  top: 0;
}

.content {
  width: 100%;
  background: lightgray;
}

.footer {
  background: pink;
  height: 800px;
}
<div>
  <div class="container">
    <div>
      <div class="sidebar normal section">
        Normal
      </div>
      <div class="sidebar sticky section">
        Sticky
      </div>
    </div>
    <div class="content">
      Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
      <br/><br/><br/><br/><br/><br/><br/><br/><br/> Content
    </div>
  </div>
  <div class="footer section">
    Footer
  </div>
</div>

  • Related