• Posted on February 13, 2015

Solve JavaScript Scroll Event Delay

JavaScript is one of those languages that has a lot of quirks. One of them that I recently ran into is how the scroll event isn’t triggered until after the page scrolls. You probably will notice this being a problem on a few sites that have sticky sidebars and headers. A sticky element is an element, such as a sidebar, that scrolls with the page and is always visible. If you notice that the sticky element lags behind by a fraction of a second when you scroll giving it a jittering effect, that site is victim to this JavaScript “flaw.”

The intended effect is to have the sticky element always in the same spot unless you are at the top of the page. The way this is generally accomplished using JavaScript is to add a scroll event listener and then modifying the position of the element in relation to the scroll and screen position. Using the example below you can see that when scrolled through using the mouse wheel, the sidebar box will jitter around.

<!doctype html>
<html>
	<head>
		<style>
			body {
				min-height: 5000px;
			}
			#sidebar {
				width: 250px;
				height: 250px;
				text-align: center;
				line-height: 250px;
				background-color: #f8f8f8;
				border: 1px solid #dddddd;
			}

		</style>
	</head>
	<body>
		<div id="sidebar">
			Side Bar Element
		</div>

		<script>
			window.addEventListener('scroll',sticky,false);

			function sticky(e) {
				var sidebar = document.getElementById('sidebar');
				sidebar.style.marginTop = (document.body.scrollTop + 10) + 'px';
			}
		</script>
	</body>
</html>

This flaw can be fixed really quickly by adding a single line of code. We have to add another event listener to listen to the mouse wheel. If you look at the previous example again, you will notice that when you scroll using the scroll bar (yup, the gray bar on the side that no one uses) the issue doesn’t exist, the problem solely lies in the mouse. Below is the updated code to fix your jittering sticky elements that rely on JavaScript. Also I am aware of CSS sticky elements and various other methods, but sometimes JavaScript is required for more advanced uses.

<!doctype html>
<html>
	<head>
		<style>
			body {
				min-height: 5000px;
			}
			#sidebar {
				width: 250px;
				height: 250px;
				text-align: center;
				line-height: 250px;
				background-color: #f8f8f8;
				border: 1px solid #dddddd;
			}

		</style>
	</head>
	<body>
		<div id="sidebar">
			Side Bar Element
		</div>

		<script>
			window.addEventListener('scroll',sticky,false);
			/* NEW LINE OF CODE BELOW */
			window.addEventListener('wheel',sticky,false);

			function sticky(e) {
				var sidebar = document.getElementById('sidebar');
				sidebar.style.marginTop = (document.body.scrollTop + 10) + 'px';
			}
		</script>
	</body>
</html>