Blur In Animation

FREE

A blur in animation for elements

Demo

Hello Blur In

Exclusive Launch 50% offspots left: 0 / 50
3D Cube - happy face3D Cube - Happy Face
$39.99

$19.99

Payment once and get lifetime access
Access to all animations
All updates
All animations
No subscriptions

Installation

1

Copy and paste the following code into your project.

Add this component blur-in.tsx to your project.

blur-in.tsx
"use client";

import React, { useEffect, useRef, useState } from "react";
import { cn } from "~/lib/utils";

interface BlurInProps {
  className?: string;
  children: React.ReactNode;
  /**
   * If true, the animation activates when the element enters the viewport.
   * If false or undefined, the animation runs immediately on mount.
   * @default false
   */
  animateOnViewport?: boolean;
  /**
   * Visibility threshold (0-1) to trigger the animation.
   * 0 = as soon as any pixel is visible
   * 1 = when the element is completely visible
   * @default 0.2
   */
  threshold?: number;
  /**
   * Animation duration in seconds
   * @default 0.7
   */
  duration?: number;
  /**
   * Initial blur intensity (in px)
   * @default 10
   */
  blurAmount?: number;
  /**
   * Change this value to reset and replay the animation.
   * Can be any value (number, string, etc.)
   */
  resetTrigger?: unknown;
}

export default function BlurIn({
  className,
  children,
  animateOnViewport = false,
  threshold = 0.2,
  duration = 0.7,
  blurAmount = 10,
  resetTrigger,
}: BlurInProps) {
  const [isVisible, setIsVisible] = useState(!animateOnViewport);
  const ref = useRef<HTMLDivElement>(null);
  const isFirstRender = useRef(true);

  // Reset animation when resetTrigger changes (skip first render)
  useEffect(() => {
    if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }

    if (resetTrigger !== undefined) {
      setIsVisible(false);
      const timer = setTimeout(() => {
        setIsVisible(true);
      }, 10);
      return () => clearTimeout(timer);
    }
  }, [resetTrigger]);

  useEffect(() => {
    if (!animateOnViewport || !ref.current) return;

    const element = ref.current;
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            setIsVisible(true);
            // Once visible, stop observing
            observer.unobserve(entry.target);
          }
        });
      },
      {
        threshold,
        rootMargin: "0px",
      },
    );

    observer.observe(element);

    return () => {
      observer.unobserve(element);
    };
  }, [animateOnViewport, threshold]);

  return (
    <div
      ref={ref}
      className={cn(
        isVisible && "animate-blur-in",
        !isVisible && "opacity-0",
        className,
      )}
      style={
        {
          "--blur-in-duration": `${duration}s`,
          "--blur-in-amount": `${blurAmount}px`,
        } as React.CSSProperties
      }
    >
      <style>{`
        .animate-blur-in {
          animation: blurIn var(--blur-in-duration, 0.7s) ease-out forwards;
        }

        @keyframes blurIn {
          from {
            filter: blur(var(--blur-in-amount, 10px));
            opacity: 0;
          }
          to {
            filter: blur(0);
            opacity: 1;
          }
        }
      `}</style>
      {children}
    </div>
  );
}

// // Examples
//?? basic usage (original behavior)
// <BlurIn className="text-4xl">
//   Content
// </BlurIn>

//?? activate animation when entering the viewport
// <BlurIn
//   className="text-4xl"
//   animateOnViewport={true}
// >
//   Content that animates when scrolling
// </BlurIn>

//?? Customized with all options (original behavior)
// <BlurIn
//   className="text-4xl"
//   animateOnViewport={true}
//   threshold={0.5}        // 50% visible
//   duration={1.2}         // 1.2 seconds
//   blurAmount={20}        // More intense blur
// >
//   Fully customized content
// </BlurIn>

//?? Reset animation dynamically
// const [resetCount, setResetCount] = useState(0);
// <BlurIn
//   className="text-4xl"
//   resetTrigger={resetCount}
// >
//   Content that can be reset
// </BlurIn>
// <button onClick={() => setResetCount(prev => prev + 1)}>Reset Animation</button>
2

Use the component BlurIn in your project.

<BlurIn
  className="text-4xl font-bold text-white"
  animateOnViewport={true}
  threshold={0.5}
  duration={1.2}
  blurAmount={20}
>
  Hello Blur In
</BlurIn>
3

Start using the animation