Vanilla JS Debouncing Header (hide on scrollDown and show on scrollUp)

HTML
<div class="o-header">Header</div>
SCSS
html { height: 200%; // just to enable scrolling } body { position: relative; } .o-header { background: yellow; padding: 2em; top: 0; position:fixed; width:100%; transition: all 200ms linear; &--hidden { transform: translateY(-80%); // change to 100% to fully hide header background: red; } }
JAVASCRIPT
var oHeader = {}; (function() { const COMPONENT = 'o-header'; const SELECTOR = document.querySelectorAll(`.${COMPONENT}`); let lastScrollPosition; /** * Init */ this.init = function() { if (SELECTOR.length !== 0) { oHeader.listen(); // Start listening ... } else { console.log(`Selector not found: '${COMPONENT}'`); } }; /** * Listen for User Input after Init */ this.listen = function() { oHeader.scroll(); // Listen for Window Scroll }; /** * Scroll * * requires debounce() */ this.scroll = function() { oHeader.setScrollPos(); window.addEventListener( 'scroll', oHeader.debounce(function() { [].slice.call(SELECTOR).forEach(el => { if (window.pageYOffset > oHeader.lastScrollPosition()) { oHeader.hide(el); } else { oHeader.show(el); } }); oHeader.setScrollPos(); }, 100) ); }; /** * Hide * * Add modifier 'hidden' to element */ this.hide = function(el) { el.classList.add(`${COMPONENT}--hidden`); }; /** * Show * * Remove modifier 'hidden' from element */ this.show = function(el) { if(el.classList.contains(`${COMPONENT}--hidden`)) { el.classList.remove(`${COMPONENT}--hidden`); } }; /** * Get Last Scroll Position */ this.lastScrollPosition = function() { return lastScrollPosition; }; /** * Set New Scroll Position */ this.setScrollPos = function() { lastScrollPosition = window.pageYOffset; }; /** * Debounce * * Returns a function, that, as long as it continues to be invoked, will not be triggered. The function will be called after it stops being called for N milliseconds. If `immediate` is passed, trigger the function on the leading edge, instead of the trailing. * From https://davidwalsh.name/javascript-debounce-function * * @param {func} func Function Callback * @param {int} wait Time in ms * @param {bool} immediate */ this.debounce = function(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; }.apply(oHeader)); document.addEventListener('DOMContentLoaded', () => { oHeader.init(); });
Expand for more options Login