8
Hooks

useScrollPosition

A hook that tracks scroll position of an element or the window.

useScrollPosition

The useScrollPosition hook tracks the scroll position of an element or the window. It’s perfect for creating scroll-based animations, sticky headers, infinite scrolling triggers, and other scroll-dependent UI behaviors.

Scroll Position:
X: 0pxY: 0px

Item 1

Scroll to see the position change

Item 2

Scroll to see the position change

Item 3

Scroll to see the position change

Item 4

Scroll to see the position change

Item 5

Scroll to see the position change

Item 6

Scroll to see the position change

Item 7

Scroll to see the position change

Item 8

Scroll to see the position change

Item 9

Scroll to see the position change

Item 10

Scroll to see the position change

Item 11

Scroll to see the position change

Item 12

Scroll to see the position change

Item 13

Scroll to see the position change

Item 14

Scroll to see the position change

Item 15

Scroll to see the position change

Item 16

Scroll to see the position change

Item 17

Scroll to see the position change

Item 18

Scroll to see the position change

Item 19

Scroll to see the position change

Item 20

Scroll to see the position change

Scroll position: 0px

Installation

Install the useScrollPosition hook using:

npx axionjs-ui add hook use-scroll-position

File Structure

use-scroll-position.ts

Parameters

PropTypeDefault
elementRef
RefObject<HTMLElement> | null
null
options
Object
{}

Options

PropTypeDefault
throttleMs
number
0

Return Value

PropTypeDefault
position
{ x: number, y: number }
-

Examples

Scroll-Based Header Effects

Create a header that changes based on scroll position:

Scroll Effects Demo

0px

Hero Section

Section 1

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 2

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 3

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 4

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 5

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 6

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 7

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 8

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 9

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Section 10

Scroll to see the header change. This demonstrates how you can create scroll-based effects.

Parallax Effect

Create a simple parallax scrolling effect:

function ParallaxSection() {
  const scrollPosition = useScrollPosition();
  
  return (
    <div style={{ position: 'relative', height: '100vh', overflow: 'hidden' }}>
      <div
        style={{
          position: 'absolute',
          top: 0,
          left: 0,
          width: '100%',
          height: '100%',
          backgroundImage: 'url(/images/background.jpg)',
          backgroundSize: 'cover',
          transform: `translateY(${scrollPosition.y * 0.5}px)`,
        }}
      />
      
      <div
        style={{
          position: 'relative',
          zIndex: 10,
          padding: '2rem',
        }}
      >
        <h1>Parallax Effect</h1>
        <p>Scroll to see the background move at a different rate.</p>
      </div>
    </div>
  );
}

Scroll-Based Progress Indicator

Create a progress bar that shows reading progress:

function ReadingProgressBar() {
  const scrollPosition = useScrollPosition();
  const [totalHeight, setTotalHeight] = useState(0);
  
  useEffect(() => {
    // Calculate the scrollable height (total height - viewport height)
    const documentHeight = document.documentElement.scrollHeight;
    const viewportHeight = window.innerHeight;
    setTotalHeight(documentHeight - viewportHeight);
    
    const handleResize = () => {
      const documentHeight = document.documentElement.scrollHeight;
      const viewportHeight = window.innerHeight;
      setTotalHeight(documentHeight - viewportHeight);
    };
    
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  
  // Calculate progress percentage
  const progress = totalHeight > 0 
    ? Math.min(100, (scrollPosition.y / totalHeight) * 100) 
    : 0;
  
  return (
    <div
      style={{
        position: 'fixed',
        top: 0,
        left: 0,
        width: '100%',
        height: '4px',
        backgroundColor: '#eee',
        zIndex: 1000,
      }}
    >
      <div
        style={{
          height: '100%',
          width: `${progress}%`,
          backgroundColor: '#0070f3',
          transition: 'width 0.1s',
        }}
      />
    </div>
  );
}

Use Cases

  • Sticky Headers: Create headers that change appearance on scroll
  • Scroll-to-Top Button: Show/hide a button based on scroll position
  • Parallax Effects: Create scroll-based parallax animations
  • Reading Progress: Display reading progress indicators
  • Lazy Loading Triggers: Load content as user approaches it
  • Infinite Scrolling: Trigger loading more content when near the bottom
  • Animation Triggers: Start animations when elements scroll into view
  • Table of Contents Highlighting: Highlight current section in a TOC
  • Scroll-Based Navigation: Change active navigation based on scroll
  • Reveal Effects: Reveal content as the user scrolls

Performance Optimization

When tracking scroll position, consider performance implications:

  1. Throttling: Use the throttleMs option to limit update frequency on rapid scrolling
  2. Use with Specific Elements: Track specific elements rather than the whole window when possible
  3. Consider requestAnimationFrame: The hook uses requestAnimationFrame internally for performance
  4. Avoid Expensive Calculations: Be mindful of calculations done with scroll values
  5. Debounce Event Handlers: Debounce any handlers that will be called with scroll position updates

Example with throttling:

// Update at most every 50ms for better performance
const scrollPosition = useScrollPosition(null, { throttleMs: 50 });

Browser Compatibility

The hook uses standard scroll properties and event listeners that are well supported across all modern browsers.

SSR Compatibility

The hook includes safeguards for server-side rendering by checking for the existence of window before attempting to access browser APIs.

Best Practices

  • Combine with CSS transitions for smoother visual effects
  • Consider mobile scrolling behavior which can be different from desktop
  • Use appropriate throttling for performance-critical applications
  • Test scroll-based interactions on various devices and browsers
  • Avoid using scroll-based effects that might interfere with user’s reading experience
  • Ensure accessibility by providing alternatives to scroll-based interactions
  • Consider user preferences like reduced motion for animations

On this page