PROWAREtech

articles » current » javascript » animate-on-scroll

JavaScript: Animate-on-Scroll

Apply a CSS class to an element when it is scrolled into view to cause it to animate.

Here is a tiny, little micro-library that adds a CSS class to an element when it is scrolled into view. This is done to enable animations of HTML elements. This Javascript code will minify to practically nothing. This file minfies to only a single kilobyte. This library is compatible with Internet Explorer 11.

Combine with the Parallax Effect JavaScript Library for more special effects. See the complete website example for more examples using this library.

The following example exaggerates the effects. In real-world use, probably use more subtle animations.


(function () {
	var setStyle = function () {
		var windowHeight = (function () {
			var o = window;
			if (o.innerHeight) {
				return o.innerHeight;
			}
			else {
				o = document;
				if (o.documentElement.clientHeight == 0) {
					return o.body.clientHeight;
				}
				else {
					return o.documentElement.clientHeight;
				}
			}
		})();
		var offset = (function () {
			var o = window;
			if (o.pageYOffset) {
				return o.pageYOffset;
			}
			else {
				o = document;
				if (o.documentElement.scrollTop == 0) {
					return o.body.scrollTop;
				}
				else {
					return o.documentElement.scrollTop;
				}
			}
		})();
		var body = document.body, html = document.documentElement;
		var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
		var divs = document.getElementsByClassName("animate-on-scroll");
		for (var i = 0; i < divs.length; i++) {
			var x = divs[i];
			var ratio = parseFloat(x.getAttribute("animate-page-ratio") || 0.8);
			if (isNaN(ratio)) {
				ratio = 0.8;
			}
			var top = Math.round(x.parentNode.getBoundingClientRect().top || 0);
			var animateClass = (x.getAttribute("animate-class") || "");
			if (windowHeight + offset >= docHeight || top <= windowHeight * ratio) {
				if (x.className.indexOf(" " + animateClass) < 0) {
					x.className += " " + animateClass;
				}
			}
			else if (top > windowHeight * ratio) {
				x.className = x.className.replace(" " + animateClass, "");
			}
		}
	};
	var addHandler = function (type) {
		var w = window;
		if (w.addEventListener) {
			w.addEventListener(type, setStyle, false);
		} else if (w.attachEvent) {
			w.attachEvent("on" + type, setStyle);
		} else {
			window["on" + type] = setStyle;
		}
	};
	addHandler("load");
	addHandler("resize");
	addHandler("scroll");
})();

Using the animate-on-scroll library requires that the class animate-on-scroll be added to each HTML element that will have a class applied to it when it is scrolled into view. Required is a parent element, like a DIV, and the animate-class attribute which is the CSS class name that is applied to the element. The animate-page-ratio is the place on the browser window where the animation will apply. For example, to have the animation begin halfway up the browser window then specify a value of 0.5 and to have the animation begin 75% down the browser window: animate-page-ratio="0.75"

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>Animate on Scroll</title>
	<style>
	body {
		background-color: lightgray;
		color: #333;
		font-family: sans-serif;
		padding: 0;
		margin: 0;
	}
	p {
		padding-left: 10px;
		padding-right: 10px;
	}
	.div-0 {
		height: 100vh;
		width: 100%;
		display: flex;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		background-color: crimson;
		color: white;
		z-index: 1;
	}
	.div-1 {
		height: 600px;
		margin: 10vmin;
		background: url(https://picsum.photos/id/47/1920/600) no-repeat;
		background-size: cover;
		opacity: 0;
		transition: 1s linear; /* this is the transition used as it scrolls out of view */
		transform: translate(-100vw, -100%);
		visibility: hidden;
	}
	.div-1-ani {
		opacity: 1;
		transform: none; /* should use "none" here to turn off transform instead of "translate(0, 0)" */
		transition: 1s cubic-bezier(.18, 0, 0, 1.2); /* this is the transition used as it scrolls into view */
		visibility: visible;
	}
	.div-2 {
		height: 600px;
		margin: 10vmin;
		background: url(https://picsum.photos/id/46/1920/600) no-repeat;
		background-size: cover;
		opacity: 0;
		transition: 1s linear;
		transform: translateY(80%);
		visibility: hidden;
	}
	.div-2-ani {
		opacity: 1;
		transform: none; /* remember, use "none" */
		transition: 2s ease-in;
		visibility: visible;
	}
	.flex-container {
		display: flex;
		margin: 10vmin;
		justify-content: center;
		align-items: center;
	}
	.div-3 {
		height: 600px;
		background: url(https://picsum.photos/id/41/1920/600) no-repeat;
		background-size: cover;
		opacity: 0;
		transition: .3s linear;
		transform: translateX(-10vw);
		flex-basis: 50%;
		visibility: hidden;
	}
	.div-3-ani {
		opacity: 1;
		transform: none;
		transition: 1s cubic-bezier(.18, 0, 0, 1.2);
		visibility: visible;
	}
	.div-4 {
		height: 480px;
		padding: 10px;
		background-color: white;
		box-shadow: 0 0 5px rgba(0,0,0,0.33);
		opacity: 0;
		transition: .3s linear;
		transform: translateX(10vmin);
		margin-left: -5vmin;
		flex-basis: 50%;
	}
	.div-4-ani {
		opacity: 1;
		transform: none;
		transition: 1s cubic-bezier(.18, 0, 0, 1.2) .5s;
	}
	.div-5 {
		height: 200px;
		width: 300px;
		margin: 10vmin auto;
		background-color: crimson;
		color: white;
		transition: 1s linear;
		transform: none;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.div-5-ani {
		background-color: green;
		transform: rotate(1turn);
		transition: 1.5s cubic-bezier(.18, 0, 0, 1.5);
	}
	.div-6 {
		height: 200px;
		width: 300px;
		margin: 10vmin auto;
		background-color: crimson;
		color: white;
		transition: 1s linear;
		transform: none;
		display: flex;
		justify-content: center;
		align-items: center;
	}
	.div-6-ani {
		background-color: blue;
		transform: rotateX(1turn) rotateY(1turn) rotateZ(1turn);
		transition: 1.5s cubic-bezier(.18, 0, 0, 1.5);
	}
	</style>
</head>
<body>

	<div class="div-0">
		<h2>Animate on Scroll</h2>
		<h3>Scroll Down</h3>
	</div>


	<div><!-- IMPORTANT: MUST BE WRAPPED WITH IN SOME KIND OF CONTAINER LIKE A div -->
		<div class="animate-on-scroll div-1" animate-page-ratio="0.5" animate-class="div-1-ani"></div>
	</div>

	<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus maiores natus in magnam. Voluptatibus rerum, quam sint saepe exercitationem omnis vitae praesentium? Enim dolor aperiam delectus molestias cumque minus dolore. Praesentium harum tempora unde suscipit dolorum est. Pariatur accusantium autem, vero cumque vel facilis alias quasi ullam sint impedit et quam repellat blanditiis nobis, quod, voluptate ut ab quaerat perferendis officiis aspernatur at laborum. Aperiam, amet magnam iusto quos nobis laudantium dolor cumque voluptatibus harum minus eum asperiores temporibus illo vitae pariatur illum quia hic deserunt! Veniam voluptatem cum accusantium officia blanditiis accusamus aperiam tempora, repellat itaque qui nulla quis?</p>

	<div>
		<div class="animate-on-scroll div-2" animate-page-ratio="0.75" animate-class="div-2-ani"></div>
	</div>

	<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus maiores natus in magnam. Voluptatibus rerum, quam sint saepe exercitationem omnis vitae praesentium? Enim dolor aperiam delectus molestias cumque minus dolore. Praesentium harum tempora unde suscipit dolorum est. Pariatur accusantium autem, vero cumque vel facilis alias quasi ullam sint impedit et quam repellat blanditiis nobis, quod, voluptate ut ab quaerat perferendis officiis aspernatur at laborum. Aperiam, amet magnam iusto quos nobis laudantium dolor cumque voluptatibus harum minus eum asperiores temporibus illo vitae pariatur illum quia hic deserunt! Veniam voluptatem cum accusantium officia blanditiis accusamus aperiam tempora, repellat itaque qui nulla quis?</p>
	<p>Inventore molestias eligendi animi amet aut officiis vero at optio cum, non blanditiis culpa possimus, rerum nemo eveniet fugit voluptatem, officia impedit. Error architecto minus autem, aliquid eum quia at, vel cum doloremque accusantium perspiciatis veniam. Consequatur incidunt iure optio qui maiores quia ipsa est debitis reiciendis alias. Sint voluptatum placeat, obcaecati dolore officiis sunt. Perspiciatis harum velit nulla quidem error atque numquam consectetur quaerat blanditiis inventore temporibus ipsam voluptates repellendus, quae ad! Dolores nobis quaerat dolore ipsum iusto ducimus velit dolorum aut et! Repellendus quis quia eos placeat impedit illo itaque nemo nisi. Velit modi impedit alias non sequi?</p>
	<p>Sapiente quibusdam natus assumenda dignissimos nostrum voluptas, vero reprehenderit nulla quo quos, iste cumque voluptate magnam dolore ea expedita ad. Ut nemo quasi optio pariatur consequatur nobis architecto non! Cupiditate recusandae rerum sed possimus non rem quisquam voluptatibus error incidunt quas voluptates at quibusdam cumque velit qui maiores quo enim, assumenda nostrum soluta numquam eum quam! Quaerat necessitatibus corrupti at nisi magni odio rem aperiam dolore. Eos eligendi sit itaque error. Eveniet exercitationem praesentium, quo dignissimos dolore vel odit, labore error neque reprehenderit aliquam doloremque amet maiores voluptatibus rerum perspiciatis. Amet quasi adipisci expedita magnam provident deleniti pariatur suscipit aperiam.</p>

	<div class="flex-container">
		<div class="animate-on-scroll div-3" animate-page-ratio="0.8" animate-class="div-3-ani"></div>
		<div class="animate-on-scroll div-4" animate-page-ratio="0.8" animate-class="div-4-ani"><h3>Lorem, ipsum dolor.</h3><p>Lorem ipsum dolor sit amet consectetur adipisicing elit ipsum dolor sit amet consectetur adipisicing elit.</p></div>
	</div>

	<p>Eaque, quas expedita cumque ipsam adipisci blanditiis doloremque nobis fuga quis recusandae quam saepe nihil iure eum animi veniam quae sapiente! Voluptatem accusantium reiciendis enim nobis, tempora culpa sequi voluptas aut suscipit sit dolorum minus atque inventore minima id eaque. Debitis temporibus, rem harum nisi dolorem in officia unde, saepe beatae excepturi expedita magni architecto, quia consectetur? Officiis, corrupti. Eum dignissimos explicabo quis consectetur enim, ad voluptatem eos molestiae iste quisquam inventore quam adipisci est? Vel repellendus molestias blanditiis asperiores libero velit, debitis aliquam ab! Nostrum hic distinctio, quae, recusandae iusto, quam porro ex expedita tenetur dicta nobis odio sequi.</p>

	<div>
		<div class="animate-on-scroll div-5" animate-page-ratio="0.65" animate-class="div-5-ani"><h1>HELLO</h1></div>
	</div>

	<p>Id nulla praesentium itaque eaque magnam ex impedit voluptate et, dolorum eveniet similique rem illo delectus laborum cum accusamus libero atque unde. Deleniti quaerat fugiat possimus excepturi eos cupiditate rem libero in, id, officiis corrupti recusandae tempore optio at nesciunt doloremque debitis facere. Aperiam nobis fugit ut porro, quis doloribus minus corporis non, ex, iure architecto cum qui sint reiciendis a eius consectetur nisi commodi nulla in dignissimos nemo fuga. In porro ea ab veritatis quas placeat numquam aperiam quos dolorem sequi, assumenda neque ipsa earum autem reiciendis labore magnam at dolorum quam vel eligendi. Dolore alias fugit unde maxime.</p>

	<div>
		<div class="animate-on-scroll div-6" animate-page-ratio="0.85" animate-class="div-6-ani"><h1>HELLO</h1></div>
	</div>

<script type="text/javascript">
(function () {
	var setStyle = function () {
		var windowHeight = (function () {
			var o = window;
			if (o.innerHeight) {
				return o.innerHeight;
			}
			else {
				o = document;
				if (o.documentElement.clientHeight == 0) {
					return o.body.clientHeight;
				}
				else {
					return o.documentElement.clientHeight;
				}
			}
		})();
		var offset = (function () {
			var o = window;
			if (o.pageYOffset) {
				return o.pageYOffset;
			}
			else {
				o = document;
				if (o.documentElement.scrollTop == 0) {
					return o.body.scrollTop;
				}
				else {
					return o.documentElement.scrollTop;
				}
			}
		})();
		var body = document.body, html = document.documentElement;
		var docHeight = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
		var divs = document.getElementsByClassName("animate-on-scroll");
		for (var i = 0; i < divs.length; i++) {
			var x = divs[i];
			var ratio = parseFloat(x.getAttribute("animate-page-ratio") || 0.8);
			if (isNaN(ratio)) {
				ratio = 0.8;
			}
			var top = Math.round(x.parentNode.getBoundingClientRect().top || 0);
			var animateClass = (x.getAttribute("animate-class") || "");
			if (windowHeight + offset >= docHeight || top <= windowHeight * ratio) {
				if (x.className.indexOf(" " + animateClass) < 0) {
					x.className += " " + animateClass;
				}
			}
			else if (top > windowHeight * ratio) {
				x.className = x.className.replace(" " + animateClass, "");
			}
		}
	};
	var addHandler = function (type) {
		var w = window;
		if (w.addEventListener) {
			w.addEventListener(type, setStyle, false);
		} else if (w.attachEvent) {
			w.attachEvent("on" + type, setStyle);
		} else {
			window["on" + type] = setStyle;
		}
	};
	addHandler("load");
	addHandler("resize");
	addHandler("scroll");
})();
</script>
	
</body>
</html>

Coding Video

https://youtu.be/2BiSAW7oggI


This site uses cookies. Cookies are simple text files stored on the user's computer. They are used for adding features and security to this site. Read the privacy policy.
CLOSE