This is a basic example of smooth scroll, it still needs to be testet in a real project.



<div data-scroll-viewport>
<div data-scroll-container>
<div class="wrap">
<!-- .wrap is only for more vertical spacing -->
<div class="row">
<div class="col-4" data-reveal="x-1">
<h2>Effect data-reveal="x-1"</h2>
</div>
<div class="col-4" data-reveal="x-1">
<h2>Effect data-reveal="x-1"</h2>
</div>
<div class="col-4" data-reveal="x-1">
<h2>Effect data-reveal="x-1"</h2>
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img3.jpg" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img2.png" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img1.jpg" />
</div>
</div>
</div>
<div class="wrap">
<!-- .wrap is only for more vertical spacing -->
<div class="row">
<div class="col-4" data-reveal="x-2">
<h2>Effect data-reveal="x-2"</h2>
</div>
<div class="col-4" data-reveal="x-2">
<h2>Effect data-reveal="x-2"</h2>
</div>
<div class="col-4" data-reveal="x-2">
<h2>Effect data-reveal="x-2"</h2>
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img3.jpg" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img2.png" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img1.jpg" />
</div>
</div>
</div>
<div class="wrap">
<!-- .wrap is only for more vertical spacing -->
<div class="row">
<div class="col-4" data-reveal="y-1">
<h2>Effect data-reveal="y-1"</h2>
</div>
<div class="col-4" data-reveal="y-1">
<h2>Effect data-reveal="y-1"</h2>
</div>
<div class="col-4" data-reveal="y-1">
<h2>Effect data-reveal="y-1"</h2>
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img3.jpg" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img2.png" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img1.jpg" />
</div>
</div>
</div>
<div class="wrap">
<!-- .wrap is only for more vertical spacing -->
<div class="row">
<div class="col-4" data-reveal="y-2">
<h2>Effect data-reveal="y-2"</h2>
</div>
<div class="col-4" data-reveal="y-2">
<h2>Effect data-reveal="y-2"</h2>
</div>
<div class="col-4" data-reveal="y-2">
<h2>Effect data-reveal="y-2"</h2>
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img3.jpg" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img2.png" />
</div>
<div class="col-4" data-reveal="img-1">
<h4>Effect data-reveal="img-1"</h4>
<img src="../assets/images/img1.jpg" />
</div>
</div>
</div>
</div>
</div>
body {
&.init-smooth-scroll {
overflow-x: hidden;
overflow-y: scroll;
}
}
[data-scroll-viewport] {
&.init-smooth-scroll {
overflow: hidden;
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
}
[data-scroll-container] {
&.init-smooth-scroll {
position: absolute;
width: 100%;
overflow: hidden;
z-index: 0;
backface-visibility: hidden;
transform-style: preserve-3d;
}
}
import { TweenLite } from "gsap/TweenMax";
export class SmoothScrollModule {
targetElmList: NodeList = document.querySelectorAll("body, [data-scroll-viewport],[data-scroll-container]");
targetElArray: HTMLElement[] = Array.prototype.slice.call(this.targetElmList);
constructor() {
if (window.innerWidth > 500) {
this.browserDetect();
}
}
private browserDetect = () => {
const detectIE = () => {
const ua = window.navigator.userAgent;
const trident = ua.indexOf("Trident/");
const msie = ua.indexOf("MSIE");
const edge = ua.indexOf("Edge/");
if (!(msie > 0 || trident > 0 || edge > 0)) {
this.smoothScroll();
this.smoothScrollStyling();
}
return false;
};
detectIE();
}
private smoothScroll = () => {
const html = document.documentElement;
const body = document.body;
const scroller = {
target: document.querySelector("[data-scroll-container]"),
ease: 0.18, // <= scroll speed
endY: 0,
y: 0,
resizeRequest: 1,
scrollRequest: 0,
};
let requestId: number | null = null;
TweenLite.set(scroller.target, {
rotation: 0.01,
force3D: true,
});
const updateScroller = () => {
const resized = scroller.resizeRequest > 0;
if (resized) {
const height = scroller.target.clientHeight;
body.style.height = height + "px";
scroller.resizeRequest = 0;
}
const scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;
scroller.endY = scrollY;
scroller.y += (scrollY - scroller.y) * scroller.ease;
if (Math.abs(scrollY - scroller.y) < 0.05 || resized) {
scroller.y = scrollY;
scroller.scrollRequest = 0;
}
TweenLite.set(scroller.target, {
y: -scroller.y,
});
requestId = scroller.scrollRequest > 0 ? requestAnimationFrame(updateScroller) : null;
};
const onScroll = () => {
scroller.scrollRequest++;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
};
const onResize = () => {
scroller.resizeRequest++;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
};
const onLoad = () => {
updateScroller();
window.focus();
window.addEventListener("resize", onResize);
document.addEventListener("scroll", onScroll);
};
setTimeout(() => {
onLoad();
}, 500);
}
private smoothScrollStyling = () => {
this.targetElArray.forEach((element: HTMLElement) => {
element.classList.add("init-smooth-scroll");
});
}
}