2

When enabling CSS scroll snap, it stops a Javascript wheel event listener from working correctly.

I have created a horizontal website that uses a wheel event listener to scroll on the X axis when scrolling with a mouse wheel.

As demonstrated below:

const scrollContainer = document.querySelector('.container');

scrollContainer.addEventListener('wheel', (e) => {
    e.preventDefault();
    scrollContainer.scrollLeft += e.deltaY;
});
* {
  margin: 0;
}

.container {
  display: flex;
  overflow-x: scroll;
  /*scroll-snap-type: x mandatory;*/
}

section {
  height: 100vh;
  width: 300vw;
  min-width: 100vw;
  /*scroll-snap-align: start;*/
}

#section1 {
  background: red;
}

#section2 {
  background: yellow;
}

#section3 {
  background: blue;
}
<html>
  <div class="container">
    <section id="section1"></section>
    <section id="section2"></section>
    <section id="section3"></section>
  </div>
</html>
  

When i add the following code to enable scroll snap:

.container {
  scroll-snap-type: x mandatory;
}

section {
  scroll-snap-align: start;
}

It stops the wheel event listener from functioning correctly, scroll snap doesn't work either.

e.preventDefault();

The preventDefault is the reason it is not working, but i am yet to find away around this problem.

Matthew98
  • 53
  • 7
  • Are you planning to add more functionality to 'wheel' addEventListener? It's not clear if you want to make snap works like it's expected (moving one by one section). When addEventListener is commented, the snap css is not working as expected. – dr_sunshine Jun 22 '22 at 06:12
  • Hi Dr_sunshine, nope i'm not planning on adding anymore functionality to the wheel event listener. The CSS Snap appears to be working for me. Did you remove the css comments? – Matthew98 Jun 22 '22 at 09:43
  • Yes. I removed JS code and remove comment for css. I'm checking in MacAirbook Chrome and iPhone Chrome. When I scroll left to right too fast, snap doesn't stop scroll on Section2 and goes to Section3 directly and same thing happen when I go from right to left. Section2 is only displayed when I scroll slow. https://www.loom.com/share/cc1546a9c6894d7eadd2a2e596cd5458 – dr_sunshine Jun 22 '22 at 10:12
  • Yup, that's normal from what i can tell. Does it do it here too? https://codepen.io/chriscoyier/full/pMRgwW – Matthew98 Jun 22 '22 at 11:19
  • Yes. it's happening on that page also. Normally snap stops at next section after each scroll. It should not scroll all the way bypassing intermediate sections. That's the purpose of snap. You can check https://www.tesla.com/ homepage also. All the sections snapping at right point and don't allow user to scroll beyond one section at a time. Same behaviour in mobile, tablet and desktop. – dr_sunshine Jun 22 '22 at 12:08
  • Hmm not sure. I've looked at more examples online and they all seem to have the same behaviour. Could Tesla be doing something else behind the scenes? Well regardless if the scroll snap is working correctly. Do you know how i could incorporate a working scroll snap with horizontal mouse scroll? – Matthew98 Jun 22 '22 at 13:22
  • I added code in answer below. You can notice the difference in scrolling behaviour. Sections are not overlapping. Check in mobile device to see the difference. – dr_sunshine Jun 22 '22 at 13:56

1 Answers1

0

note the changes marked with code added. I removed JS code. Seems tesla is using additional scroll-snap-stop property to stop at each snap point. The behaviour is more observable in mobile device.

* {
  margin: 0;
}

.container {
  display: flex;
  overflow-x: scroll;
  -ms-scroll-snap-destination: 0 0; /* code added */
  scroll-snap-destination: 0 0; /* code added */
  -ms-scroll-snap-type: x mandatory; /* code added */
  scroll-snap-type: x mandatory;
}

section {
  height: 100vh;
  width: 100vw;
  min-width: 100vw;
  scroll-snap-align: start;
  scroll-snap-stop: always; /* code added */
}

#section1 {
  background: red;
}

#section2 {
  background: yellow;
}

#section3 {
  background: blue;
}
<html>
  <div class="container">
    <section id="section1"></section>
    <section id="section2"></section>
    <section id="section3"></section>
  </div>
</html>
dr_sunshine
  • 91
  • 2
  • 8
  • Thank you for that dr_sunshine, were you able to get the JS code to create a horizontal scroll when the user scrolls vertical on their mouse working? It doesn't look like it is possible as the preventDefault() stops the css code. From what i can think of, the only methods would be to create the scroll snap in javascript or do some css dom manipulation by rotating the parent and child containers the opposite ways. Any thoughts? – Matthew98 Jun 22 '22 at 14:28
  • Yes. I don't think "css snap" and "js wheel" will go smoothly together. There are only 3 possibilities. 1. use css snap for horizontal scroll (preferred) 2. use "css snap" for horizontal scroll and js wheel to handle vertical scroll (you'll need to write resolution specific js, but even if you achieve some part, scroll experience will be glitchy) 3. use js only solution for both vertical and horizontal scroll (again it'll be time consuming and you won't be able achieve expected scroll behaviour) – dr_sunshine Jun 23 '22 at 07:15
  • Ok thank you for your reply. I have implemented it with JS by using the wheel scroller listener and an Intersection observer but it is a little glitchy. May try one final time with a CSS scroll snap by rotating the page. – Matthew98 Jun 23 '22 at 08:07