skip to Main Content

I have a .job-banner div in the middle of my page with CSS position:sticky and javascript watcher adding a "sticky" class whenever scrolling past it. Due to the style guide I need to apply different spacing and font size within .job-banner when it’s sticky. I found that my implementation often glitches when scrolling and I’m not sure how to fix it.

Here is a simplified Codepen to demonstrate: https://codepen.io/anzuj/pen/GRzqPGP

Any tips would be welcome!

2

Answers


  1. To fix your glitching, you’re going to have to make several changes.

    The first thing you need to do is not have the banner sticky unless the .sticky class is added. The reason this is important is it will allow you to scroll past the top of the banner.

    Revised CSS:

    .job-banner {
      /* position: sticky */ /* don't have the display: sticky property normally */;
      top:0;
      z-index:900;
      background: #f5f5f5;
       transition: all 0.3s ease-in-out;
       font-size: 1.2rem; 
     
    }
    
    .job-banner.sticky {
      position:sticky; /* when this sticky class is added to the banner, now make it sticky */
    }
    

    But that won’t do much unless you make some changes to the JavaScript too:

    const $stickyElement = $('.job-banner');
    
    $(window).scroll(function() {
      var scrollTop = $(window).scrollTop();
        var elementTop = $stickyElement.offset().top;
      if (scrollTop  >= elementTop + 70) { // this allows you to scroll at least 70 pixels past the top of the element before the sticky class is added. You can make it 80 if you want
        $stickyElement.addClass('sticky');
      } else if (scrollTop < elementTop) { // only change back if you are up past the banner's top
        $stickyElement.removeClass('sticky');
      }
    })
    

    What this does is it allows you to scroll 70 pixels past the banner, allowing you to skip the glitching effect.

    Login or Signup to reply.
  2. It jumps because you resize it.
    Use position: fixed; and account for resizing. This can be done by giving the height to the parent. Somehow:

    const $stickyElement = $('.job-banner');
    
    $(window).on('load scroll resize', function() {
      if (!$stickyElement.length) {
        return;
      }
      const scrollTop = $(window).scrollTop();
      const elementTop = $stickyElement.offset().top;
      if (scrollTop >= elementTop) {
        $stickyElement
          .css({
            height: $stickyElement.height(),
            '--width': $stickyElement.width() + 'px'
          })
          .addClass('sticky');
      } else {
        $stickyElement.removeClass('sticky');
      }
    })
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    body {
      background-color: #ffffff;
      font-family: "OpenSans-Regular", sans-serif;
      line-height: 24px;
      font-size: 17px;
      min-height: 100vh;
    }
    
    main {
      max-width: 1440px;
      margin: 0 auto;
    }
    
    .job-banner {
      background: #f5f5f5;
      font-size: 1.2rem; 
    }
    
    .job-banner h1 {
      margin-bottom: 1rem;
    }
    
    .job-banner .inner-wrapper {
      padding: 30px 30px 30px 100px;
    }
    
    .job-banner.sticky .inner-wrapper {
      position: fixed;
      top: 0;
      padding: 10px;
      z-index: 900;
      background: #f5f5f5;
      width: var(--width);
    }
    
    .job-banner.sticky h1 {
      font-size: 1rem;
      margin: 0;
    }
    
    .section1 {
      height: 180px;
      background-color: #C9F3F3;
      margin-bottom: 30px;
      padding: 30px;
      text-align: center
    }
    
    .section2 {
      margin-top: 30px;
      height: 2200px;
      background-color: #C9F3F3;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <main>
      <section class="section1">
        Problem: when slowly scrolling up and down, sometimes the sticky banner glitches because of padding/ h1 font size change.
      </section>
      <div class="job-banner">
        <div class="inner-wrapper">
          <h1>Loremipsum dolor sit amet, consectetur a</h1>
          <p>Quisque sed nulla eget sapien porta</p>
        </div>  
      </div>
      <section class="section2"></section>
    </main>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search