Custom Cursor Override

Custom Cursor Override

Custom Cursor Override

Custom Cursor Override

Effect

Effect

Effect

Effect

Custom Cursor Override

Custom Cursor Override

Custom Cursor Override

Custom Cursor Override

This is a code override you can use to create a custom "circle" cursor for your Framer website. This effect was inspired by the amazing website of Eythan D'Amico.

This is a code override you can use to create a custom "circle" cursor for your Framer website. This effect was inspired by the amazing website of Eythan D'Amico.

This is a code override you can use to create a custom "circle" cursor for your Framer website. This effect was inspired by the amazing website of Eythan D'Amico.

This is a code override you can use to create a custom "circle" cursor for your Framer website. This effect was inspired by the amazing website of Eythan D'Amico.

Custom Cursor Override
Custom Cursor Override
Custom Cursor Override
Custom Cursor Override

Features

You can create a "Custom Cursor" frame and apply the code override you find below. This will turn that frame into your cursor on the website.

Check out the full guide about the implementation here.

Step 01 outline

Step / 01

Copy the code override.

Step 2 outline

Step / 02

Create an override with it in your project.

Step 3 outline

Step / 03

Create a cursor frame.

Step 4 outline

Step / 04

Apply the override to it.

Custom cursor code override

Here's the code you need to copy and create a code override file in your project. Afterward, just apply that code override to your cursor frame to transform it into your custom cursor.

import type { ComponentType } from "react"
import { useRef, useState, useEffect } from "react"
import { motion, useSpring } from "framer-motion"

function hasButtonOrAnchorAncestor(element: HTMLElement | null): boolean {
    if (!element) {
        return false
    }

    if (element.tagName === "BUTTON" || element.tagName === "A") {
        return true
    }

    return hasButtonOrAnchorAncestor(element.parentElement)
}

export function withCursorFollow(Component: ComponentType): ComponentType {
    return (props: any) => {
        if (typeof document === "undefined") {
            return null as any
        }

        // Add a style tag to the head of the document to hide the system cursor for all elements
        const style = document.createElement("style")
        style.appendChild(
            document.createTextNode("* { cursor: none !important; }")
        )
        document.head.appendChild(style)

        const cursorRef = useRef(null)
        const [isHovering, setIsHovering] = useState(false)

        const spring = {
            type: "spring",
            stiffness: 1000,
            damping: 70,
        }

        const storedPosition = localStorage.getItem("cursorPosition")
        const initialCursorPosition = useRef(
            storedPosition
                ? JSON.parse(storedPosition)
                : { x: window.innerWidth / 2, y: window.innerHeight / 2 }
        )

        const positionX = useSpring(initialCursorPosition.current.x, spring)
        const positionY = useSpring(initialCursorPosition.current.y, spring)

        useEffect(() => {
            const handleMouseMove = (e: MouseEvent) => {
                if (!cursorRef.current) return

                // Check if the cursor is hovering a button or "A" tag element
                const isHovered =
                    e.target instanceof HTMLElement &&
                    (e.target.tagName === "BUTTON" ||
                        e.target.tagName === "A" ||
                        hasButtonOrAnchorAncestor(e.target.parentElement))
                setIsHovering(isHovered)

                // Update the position based on the cursor position
                positionX.set(e.clientX)
                positionY.set(e.clientY)

                localStorage.setItem(
                    "cursorPosition",
                    JSON.stringify({ x: e.clientX, y: e.clientY })
                )
            }

            // Store the initial cursor position when the component is first rendered
            initialCursorPosition.current.x = window.innerWidth / 2
            initialCursorPosition.current.y = window.innerHeight / 2

            window.addEventListener("mousemove", handleMouseMove)
            return () => {
                window.removeEventListener("mousemove", handleMouseMove)
            }
        }, [])

        return (
            <motion.div
                ref={cursorRef}
                style={{
                    position: "fixed",
                    left: positionX,
                    top: positionY,
                    pointerEvents: "none",
                    transform: "translate(-50%, -50%)",
                    transition: "transform 0.2s ease, opacity 0.2s ease",
                    zIndex: 9999,
                    opacity: isHovering ? 0.5 : 1, // Adjust opacity on hovering interactive elements
                    scale: isHovering ? 1.7 : 1, // Adjust scale on hovering interactive elements
                }}
            >
                <Component {...props} />
            </motion.div>
        )
    }
}
import type { ComponentType } from "react"
import { useRef, useState, useEffect } from "react"
import { motion, useSpring } from "framer-motion"

function hasButtonOrAnchorAncestor(element: HTMLElement | null): boolean {
    if (!element) {
        return false
    }

    if (element.tagName === "BUTTON" || element.tagName === "A") {
        return true
    }

    return hasButtonOrAnchorAncestor(element.parentElement)
}

export function withCursorFollow(Component: ComponentType): ComponentType {
    return (props: any) => {
        if (typeof document === "undefined") {
            return null as any
        }

        // Add a style tag to the head of the document to hide the system cursor for all elements
        const style = document.createElement("style")
        style.appendChild(
            document.createTextNode("* { cursor: none !important; }")
        )
        document.head.appendChild(style)

        const cursorRef = useRef(null)
        const [isHovering, setIsHovering] = useState(false)

        const spring = {
            type: "spring",
            stiffness: 1000,
            damping: 70,
        }

        const storedPosition = localStorage.getItem("cursorPosition")
        const initialCursorPosition = useRef(
            storedPosition
                ? JSON.parse(storedPosition)
                : { x: window.innerWidth / 2, y: window.innerHeight / 2 }
        )

        const positionX = useSpring(initialCursorPosition.current.x, spring)
        const positionY = useSpring(initialCursorPosition.current.y, spring)

        useEffect(() => {
            const handleMouseMove = (e: MouseEvent) => {
                if (!cursorRef.current) return

                // Check if the cursor is hovering a button or "A" tag element
                const isHovered =
                    e.target instanceof HTMLElement &&
                    (e.target.tagName === "BUTTON" ||
                        e.target.tagName === "A" ||
                        hasButtonOrAnchorAncestor(e.target.parentElement))
                setIsHovering(isHovered)

                // Update the position based on the cursor position
                positionX.set(e.clientX)
                positionY.set(e.clientY)

                localStorage.setItem(
                    "cursorPosition",
                    JSON.stringify({ x: e.clientX, y: e.clientY })
                )
            }

            // Store the initial cursor position when the component is first rendered
            initialCursorPosition.current.x = window.innerWidth / 2
            initialCursorPosition.current.y = window.innerHeight / 2

            window.addEventListener("mousemove", handleMouseMove)
            return () => {
                window.removeEventListener("mousemove", handleMouseMove)
            }
        }, [])

        return (
            <motion.div
                ref={cursorRef}
                style={{
                    position: "fixed",
                    left: positionX,
                    top: positionY,
                    pointerEvents: "none",
                    transform: "translate(-50%, -50%)",
                    transition: "transform 0.2s ease, opacity 0.2s ease",
                    zIndex: 9999,
                    opacity: isHovering ? 0.5 : 1, // Adjust opacity on hovering interactive elements
                    scale: isHovering ? 1.7 : 1, // Adjust scale on hovering interactive elements
                }}
            >
                <Component {...props} />
            </motion.div>
        )
    }
}

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free
Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.

Free Framer Course

Learn how to create stunning websites with ease by learning the fundamentals of Framer.