Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scroll Bouncing With Fixed Positioning

I have a fixed element that attaches on my page when you reach it in the scroll. This element can sometimes have content above it but not below it, meaning the page depth might not be deep enough to support this kind of behavior, because of this it prevents the user from reaching the bottom of the page and causes the page to bounce, presumably because it's removing the element from the scroll when it fixes, which causes the condition in the scroll event function to no longer be true. The gif shows the undesired effect when this happens.

enter image description here

Demonstrated here in this fiddle: https://jsfiddle.net/dcsjx625/8/

The pages are dynamic so removing the effect for a single page is not possible.

<body>
  <div class="header">
    <img src="http://placehold.it/600x401">
  </div>
  <div class="content-parent">
    <div class="content">
      <img src="http://placehold.it/600x400">
      <img src="http://placehold.it/600x400">
      <img src="http://placehold.it/600x400">
    </div>
  </div>
  <div class="footer-content">
  Footer
  </div>
</body>

jQuery:

var $stickyChainOffset = $('.content').offset();
var $stickyChain = $('.content');
var $fixedWidth = $('.content').parent().width();

function checkScroll() {
  if ($(window).scrollTop() > $stickyChainOffset.top - 100) {
    $stickyChain.css('position', 'fixed').css('top', '100px').css('max-width', $fixedWidth);
  } else {
    $stickyChain.css('position', 'static').css('max-width', 'initial');
  }
};

$(window).scroll(function() {
  checkScroll();
});

/* Updates the $fixedWidth variable on resize */
$(window).resize(function() {
  $fixedWidth = $('.content').parent().width();
  $(window).scroll();
});

Ideally I want to prevent the sticking effect if the element is close enough to the bottom of the page that it might cause a problem.

I've tried calculating the page depth vs the element height in the checkScroll() function like so but even this isn't working. I feel like I'm right on the edge of solving this.:

function checkScroll() {
  height = $stickyChain.height() + 100;
  depth = $(document).height() - $stickyChainOffset.top;

  if ($(window).scrollTop() > $stickyChainOffset.top - 100 && depth > height) {
    $stickyChain.css('position', 'fixed').css('top', '100px').css('max-width', $fixedWidth);
  } else {
    $stickyChain.css('position', 'static').css('max-width', 'initial');
  }
};

Any help would be greatly appreciated!

like image 911
James Ives Avatar asked Oct 18 '22 18:10

James Ives


1 Answers

I gotta be honest, I understand your problem but I have no idea when and why you'd run into this exact behavior. That said, here's my workaround and some notes:

  1. The height of your content needs to be 2x the height of fixed element in order to maintain the scrollbar. Otherwise, once the element is fixed, your document entirely loses the scrollbar.
  2. I'm saving the original offset of fixed element to a variable that is used as a marker for future reset. However, I am also redefining the $stickyChainOffset in every scroll event, that you used to define only once. I'm doing this because it changes once fixed.
  3. You can comment and uncomment the padding I saved in css to see how the page behaves in various cases.

If you have any other questions, let me know.

https://jsfiddle.net/1fke1j3d/1/

like image 177
Serg Chernata Avatar answered Oct 20 '22 09:10

Serg Chernata