Docs
Cutout Text Loader
A cutout text loader is a loading animation where the text appears "cut out," revealing a moving gradient or background animation through the letters.
Installation
Install dependencies
npm install framer-motion lucide-react
Run the following command
It will create a new file cutout-text-loader.tsx
inside the components/mage-ui/preloader
directory.
mkdir -p components/mage-ui/preloader && touch components/mage-ui/preloader/cutout-text-loader.tsx
Paste the code
Open the newly created file and paste the following code:
"use client";
import React, { useState, useEffect } from "react";
const CutOut: React.FC = () => {
return (
<div className="h-screen w-[90vw]"> {/* Added h-screen and w-[90vw] */}
<CutoutTextLoader
height="100%" // Changed to 100% to fill the parent
background="white"
imgUrl="https://images.unsplash.com/photo-1635373670332-43ea883bb081?q=80&w=2781&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
/>
</div>
);
};
interface CutoutTextLoaderProps {
height: string;
background: string;
imgUrl: string;
}
const CutoutTextLoader: React.FC<CutoutTextLoaderProps> = ({
height,
background,
imgUrl,
}) => {
const [imageLoaded, setImageLoaded] = useState<boolean>(false); // State to track image loading
useEffect(() => {
const img = new Image();
img.src = imgUrl;
img.onload = () => {
setImageLoaded(true);
};
img.onerror = () => {
console.error("Error loading image:", imgUrl);
// Handle the error appropriately (e.g., display a fallback image)
};
return () => {
// Cleanup: Remove the event listeners when the component unmounts
img.onload = null;
img.onerror = null;
};
}, [imgUrl]);
return (
<div className="relative h-full" style={{ height }}> {/* h-full to take the full height of its parent */}
<div
className="absolute inset-0 z-0"
style={{
backgroundImage: `url(${imgUrl})`,
backgroundPosition: "center",
backgroundSize: "cover",
opacity: imageLoaded ? 1 : 0, // Initially hide the image
transition: "opacity 0.5s ease-in-out", // Fade in when loaded
}}
/>
<div
style={{ background }}
className={`absolute inset-0 z-10 ${!imageLoaded ? "animate-pulse" : "animate-pulse"}`} // Conditionally apply animation
/>
<span
className="font-black absolute inset-0 z-20 text-center bg-clip-text text-transparent pointer-events-none items-center flex justify-center"
style={{
backgroundImage: `url(${imgUrl})`,
backgroundPosition: "center",
backgroundSize: "cover",
fontSize: "clamp(3rem, 12vw, 10rem)",
lineHeight: height,
}}
>
Loading...
</span>
</div>
);
};
export default CutOut;