Search code examples
htmlcssscrollscroll-snapscroll-snap-type

Website double-scrolling on Chrome using scroll-snap-type


I want my sections to take the whole page and as soon as the user scrolls up or down, the previous/next section comes up. It works perfectly on Firefox and on Chromium-Edge, but when I tested it on Chrome, it always skips a section (goes from section1 to section 3 and from section 3 back to section 1). What can I do to solve this problem?

Here is the HTML:

<div class="page container">
    <div class="section section1">
       ...
    </div>

    <div class="section section1">
       ...
    </div>

    <div class="section section2">
       ...
    </div>

    <div class="section section3">
       ...
    </div>
</div>

And here is the CSS:

    .container{
  position: relative;
  width: 100%;
  height: 100vh;
  overflow: auto;

  /*  Scroll Snap  */

  scroll-snap-type: y mandatory;
}

.section{
  position: relative;
  width: 100%;
  height: 100%;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  justify-content: center;
}

here is the website if anyone wants to see by themselves : Open in Firefox and/or Chrome to see difference


Solution

  • Definitely a bug in Chrome. The offender seems to be background-color (!) property set on the container element.

    For some inexplicable reasons its presence triggers overscrolling... BUT only on a wheel-kind scroll. The keyboard one (either with KeyUp/Down or PageUp/Down) works fine.

    Here's SRE; try scrolling the page, then press 'Fix Chrome' button, then scroll one more time - and see the difference. In Chrome 86 (Version 86.0.4240.111 (Official Build) (64-bit), to be precise), at least.

    body {
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    
    .break-things {
      background-color: #f3f3f3;
    }
    
    .container {
      position: relative;
      width: 100%;
      height: 100vh;
      scroll-snap-type: y mandatory;
      overflow-y: scroll;
    }
    
    .item {
      scroll-snap-align: start;
      font-size: 7rem;
      height: 77vh; 
    }
    
    .item1 {
      background-color: blue;
    }
    
    .item2 {
      background-color: yellow;
    }
    
    .item3 {
      background-color: red;
    }
    <body>
      <header><button type=button>FIX CHROME SCROLL SNAP</button></header>
      <div class="container break-things">
        <div class="item item1">Hello World</div>
        <div class="item item2">Hello World</div>
        <div class="item item3">Hello World</div>
      </div>
      <script>
       let isChromeBroken = true;
       document.querySelector('button').onclick = (ev) => {
         isChromeBroken = !isChromeBroken;
         ev.target.textContent = `${isChromeBroken ? 'FIX' : 'BREAK'} CHROME SCROLL SNAP`;
         document.querySelector('.container').classList.toggle('break-things');   
       }
      </script>
    </body>