I made a website that makes use of Bootstrap 4, horizontal scrolling (via jquery.mousewheel.js) and native CSS Snapping. I am using Chrome 81, and don't care about old/unsupported browsers.
When I apply scroll-snap-type: x mandatory;
to CSS, the horizontal scrolling stops working (no scrolling happens at all). If the CSS property is removed, the scrolling behaves normally. Here is my HTML structure:
<div class="portfolio_content container-fluid h-100">
<div class="row h-100 flex-row flex-nowrap scrollx long_content">
<div class="col-12 h-100 project d-table" id="project1">
<div class="project_title d-table-cell align-middle">
<p>
Project 1
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project2">
<div class="project_title d-table-cell align-middle">
<p>
Project 2
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project3">
<div class="project_title d-table-cell align-middle">
<p>
Project 3
</p>
</div>
</div>
<div class="col-12 h-100 project d-table" id="project4">
<div class="project_title d-table-cell align-middle">
<p>
Project 4
</p>
</div>
</div>
</div>
</div>
For CSS, the key entries are here:
html, body {
height: 100%;
}
.portfolio_content .scrollx {
overflow-x: scroll;
}
.portfolio_content .long_content {
scroll-snap-type: x mandatory; /* Comment this to make scrolling works */
}
.portfolio_content .project {
scroll-snap-align: start;
}
.portfolio_content .project_title {
display: block;
margin: auto;
text-align: center;
}
.portfolio_content .project_title h1 {
font-size: 96px;
line-height: 0.8;
}
Last, here is the JSFiddle demo. If you comment line 9 in CSS, the demo will be able to scroll.
My aim is to allow the "project" DIV to be snapped when scrolling, i.e. one "project" DIV will be fully shown after scrolling.
How should I change the codes?
Short answer: take away the javascript code.
Long answer:
mousewheel.js
is useful if you want to check or do something on wheel events. In this case, you simply want to let the browser scroll. You are taking control of that event in the function and preventing the default, but the default action is exactly what you want.When you execute
this.scrollLeft -= delta;
, it does two things:scroll
and thenend scroll
. thescroll-snap-type
listens toend scroll
and snaps the element. Actually, if you take away only thee.preventDefault();
line, a funny thing happens. The element vibrates and then changes. In my understanding, what is happening is: 1) Default scroll event, which takes some time. Meanwhile, 2) wheel event, which triggers a much shorter scroll event. 3) snap. Since thedeltaX
from 2 is small, you get to the starting position. repeat 2 and 3 several times. 4) Default scroll event ends with a much largerdeltaX
. 5) snap.In summary, for the behavior you want, it is better to let the browser do the scrolling. If you want to do something else, you need to avoid sending an
end scroll
signal every time amousewheel
event fires. To do that, you can simply eliminate the two lines of code inside the mousewheel function and add the code you need.EDIT after comment:
I should have guessed by the context, you want to transform vertical wheel events into horizontal wheel events. The former answer works if you send a horizontal wheel event (you can do that with a touchpad). The long answer still stands, so the question is how to bypass the problem. I thought of a couple of strategies:
WheelEvent
. By far the most elegant solution, but I could not make it work. The event gets dispatched but no scrolling occurs:scrollBy
, which seems to work better if using thesmooth
behavior: https://jsfiddle.net/9rbgdh6y/1/ .EDIT 2
There are many strategies to make this work, but all of them have their disadvantages. The previous one had minimal impact on your script, but the change started after the wheel event ended. This and other parameters are left to the browser, and will not be under your control.
I have added a second fiddle with another strategy that gives the behavior you seem to want (https://jsfiddle.net/vhywmdb5/). I hope it helps, but every solution needs to be tweaked and there are no warranties that it will work with every browser. Unfortunately, the event simulation in
mousewheel.js
is broken at this time.