Scroll offset - markhowellsmead/helpers GitHub Wiki

Add scroll offset to the page

Adds a scroll offset to the page, to stop anchor disappearing behind a fixed header.

/**
 * Adjusts the HTML element offset because of a fixed
 * header. The value of --scroll-padding-top should be 
 * applied to the HTML element element in CSS.
 * 
 * [email protected], this version 7.2.2021
 */

const masthead = document.querySelector('.c-masthead');
document.documentElement.style.setProperty('--scroll-padding-top', 0);

const setAnchorOffset = function () {
    const height = Math.floor(masthead.offsetHeight);
    document.documentElement.style.setProperty('--scroll-padding-top', `${height}px`);
};

setAnchorOffset();
window.addEventListener('load', setAnchorOffset);
window.addEventListener('resize', setAnchorOffset);
window.addEventListener('orientationchange', setAnchorOffset);
window.addEventListener('scroll', setAnchorOffset);
html {
    /* Will be overridden by JS */
    --scroll-padding-top: 0;
    scroll-padding-top: var(--scroll-padding-top);
}


/* Account for sub-pixel rendering */
[id] {
    scroll-snap-margin-top: -0.5px;
    scroll-margin-top: -0.5px;
}

Track scroll direction

Add/remove a CSS class on the document root (html) when scrolling, according to the scroll direction.

/**
 * Show masthead on scroll up
 * Hide masthead on scroll down to 1/4 of the window height
 */
let lastScrollTop = 0;
window.addEventListener('scroll', function () {
	let currentScrollTop = html.scrollTop;
	let cutoff = window.innerHeight / 4;

	if (currentScrollTop > lastScrollTop) {
		// scrolling down
		html.classList.remove('is--scrolling-up');
		html.classList.add('is--scrolling-down');

		if (currentScrollTop > cutoff) {
			masthead.classList.add('is--stuck');
		}
	} else {
		// scrolling up
		masthead.classList.remove('is--stuck');

		if (currentScrollTop === 0) {
			html.classList.remove('is--scrolling-up');
			html.classList.remove('is--scrolling-down');
		} else {
			html.classList.remove('is--scrolling-down');
			html.classList.add('is--scrolling-up');
		}
	}
	lastScrollTop = currentScrollTop <= 0 ? 0 : currentScrollTop; // For Mobile or negative scrolling
});