SmoothScroll with reaveal

Scroll down to see effect and sourcecode, reload if vue dosent init smoothscrollscript

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

Dependencies

  • Tweenmax from GSAP

Effect data-reveal="x-1"

Effect data-reveal="x-1"

Effect data-reveal="x-1"

Effect data-reveal="x-2"

Effect data-reveal="x-2"

Effect data-reveal="x-2"

Effect data-reveal="y-1"

Effect data-reveal="y-1"

Effect data-reveal="y-1"

Effect data-reveal="y-2"

Effect data-reveal="y-2"

Effect data-reveal="y-2"

Html


<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>

Scss

		
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;
	}
}

JavaScript

 
	
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");
		});
	}
}