It is very annoing to hold shift when wheeling for horizontal scrolling. There are some ways to horizontally scrool with wheel only but they directly copy wheel deltaY
into scrollLeft
which results in uncomfortable jump-scrolling.
Is there a mobile-friendly way to perform smooth horizontal scrolling on elements using wheel only? By "smooth" I mean something like default browser vertical wheel scroll behaviour.
Smooth scrolling can be achieved by using requestAnimationFrame
.
You might want to play with denominator in getScrollStep
function to adjust the smoothness of scrolling.
function horizontalWheel(container) {
/** Max `scrollLeft` value */
let scrollWidth;
/** Desired scroll distance per animation frame */
let getScrollStep = () => scrollWidth / 50 /* ADJUST TO YOUR WISH */ ;
/** Target value for `scrollLeft` */
let targetLeft;
function scrollLeft() {
let beforeLeft = container.scrollLeft;
let wantDx = getScrollStep();
let diff = targetLeft - container.scrollLeft;
let dX = wantDx >= Math.abs(diff) ? diff : Math.sign(diff) * wantDx;
// Performing horizontal scroll
container.scrollBy(dX, 0);
// Break if smaller `diff` instead of `wantDx` was used
if (dX === diff)
return;
// Break if can't scroll anymore or target reached
if (beforeLeft === container.scrollLeft || container.scrollLeft === targetLeft)
return;
requestAnimationFrame(scrollLeft);
}
container.addEventListener('wheel', e => {
e.preventDefault();
scrollWidth = container.scrollWidth - container.clientWidth;
targetLeft = Math.min(scrollWidth, Math.max(0, container.scrollLeft + e.deltaY));
requestAnimationFrame(scrollLeft);
});
}
Just pass elements you want to horizontally scroll with wheel in this function:
let list = document.querySelector('.hList');
horizontalWheel(list);
Example:
function horizontalWheel(container) { /** Max `scrollLeft` value */ let scrollWidth; /** Desired scroll distance per animation frame */ let getScrollStep = () => scrollWidth / 50 /* ADJUST TO YOUR WISH */; /** Target value for `scrollLeft` */ let targetLeft; function scrollLeft() { let beforeLeft = container.scrollLeft; let wantDx = getScrollStep(); let diff = targetLeft - container.scrollLeft; let dX = wantDx >= Math.abs(diff)? diff: Math.sign(diff) * wantDx; // Performing horizontal scroll container.scrollBy(dX, 0); // Break if smaller `diff` instead of `wantDx` was used if (dX === diff) return; // Break if can't scroll anymore or target reached if (beforeLeft === container.scrollLeft || container.scrollLeft === targetLeft) return; requestAnimationFrame(scrollLeft); } container.addEventListener('wheel', e => { e.preventDefault(); scrollWidth = container.scrollWidth - container.clientWidth; targetLeft = Math.min(scrollWidth, Math.max(0, container.scrollLeft + e.deltaY)); requestAnimationFrame(scrollLeft); }); } // // Usage // window.addEventListener('load', () => { let list = document.querySelector('.hList'); horizontalWheel(list); });
.hList { width: 300px; border: 2px solid red; display: flex; overflow: auto; }.element { display: flex; align-items: center; justify-content: center; color: white; font-family: sans-serif; flex-shrink: 0; width: 150px; height: 75px; background: green; border-right: 2px solid yellow; }.element:last-of-type { border: none; }
<div class="hList"> <div class="element">Element 1</div> <div class="element">Element 2</div> <div class="element">Element 3</div> <div class="element">Element 4</div> <div class="element">Element 5</div> </div>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.