useVisible() Hook

Intersection Observer simplified

The useVisible() hook allows you to easily determine if a referenced DOM element is within the viewport. This is particularly useful for triggering animations or actions when the user scrolls to a specific section of the page. It returns a boolean indicating the visibility of the element.


import { useState, useEffect, RefObject } from 'react'

export const useElementVisibility = (elementRef: RefObject<Element>): boolean => {
const [isVisible, setIsVisible] = useState(false);

useEffect(() => {
const targetElement = elementRef.current;

// Function to monitor visibility changes
const onVisibilityChange = (entries: IntersectionObserverEntry[]) => {
  const [entry] = entries;

// Initialize Intersection Observer to watch visibility changes if target exists
if (targetElement) {
  const visibilityObserver = new IntersectionObserver(onVisibilityChange, {
    root: null, // viewport is the observational reference
    rootMargin: '0px 0px 600px 0px', // margins around the root
    threshold: 0.01, // minimum portion of the target visible for callback


  // Cleanup by disconnecting observer when component is unmounted
  return () => visibilityObserver.disconnect();

}, [elementRef]); // Effect dependencies

return isVisible;

Example Usage

As a user scrolls through a web page, the FadeInComponent transitions from being transparent to fully visible, creating a smooth fade-in effect. it's a simple example of how the useVisible() hook can be used to trigger animations based on the visibility of an element.


import React, { useRef } from 'react';
import { useVisible } from '@/hooks/useVisible';

const FadeInComponent = () => {
const ref = useRef(null); // Create a ref for the component we want to observe.
const isVisible = useVisible(ref); // Use the hook to check visibility.

return (

  className={`bg-light-blue-500 h-72 w-full transition-opacity duration-1000 ease-in-out ${
    isVisible ? 'opacity-100' : 'opacity-0'
  <p className="pt-32 text-center text-white">
    {isVisible ? '🎉 I am now visible!' : 'Scroll down to see me appear!'}
); };

export default FadeInComponent;