Skip to content

Instantly share code, notes, and snippets.

@khasky
Created April 8, 2026 06:41
Show Gist options
  • Select an option

  • Save khasky/4ef0abb891d4a92f98cc42ea25cac25a to your computer and use it in GitHub Desktop.

Select an option

Save khasky/4ef0abb891d4a92f98cc42ea25cac25a to your computer and use it in GitHub Desktop.
useScrollDirection React Hook
// Subscribes to `scroll` (passive) and exposes whether the user is moving
// down the page, up, or still in the “top” band (y === 0 or within ~40px while settling).
import { useEffect, useState } from 'react';
export enum ScrollDirection {
Top = -1,
Initial = 0,
Bottom = 1,
}
export function useScrollDirection() {
const [direction, setDirection] = useState<ScrollDirection>(ScrollDirection.Initial);
let prevScroll = 0;
if (typeof window !== 'undefined') {
prevScroll = window.scrollY;
}
const handleScroll = () => {
const currScroll = window.scrollY;
const isInitialPosition = currScroll === 0 || (prevScroll <= currScroll && currScroll <= 40);
const isScrollingBottom = currScroll > prevScroll;
if (isInitialPosition) {
setDirection(ScrollDirection.Initial);
} else {
setDirection(isScrollingBottom ? ScrollDirection.Bottom : ScrollDirection.Top);
}
prevScroll = currScroll;
};
useEffect(() => {
window.addEventListener('scroll', handleScroll, { passive: true });
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return direction;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment