Magnetic Button Override in Framer

Copy component

Copy component

Magnetic Button Override in Framer

Copy component

Nandi Muzsik

How can I improve Framer Uni?

Let me know if there’s a missing feature or something that could be improved.

Share feedback

How to Make $10K+ with Framer in 60 days

How to Make $10K+ with Framer in 60 days

Effect

Magnetic Button Override in Framer

This is a code override for Framer that you can slap onto any element to make it magnetic. When you hover over the element, it starts following the cursor, and then snaps back to its original position when the cursor moves further away.

image of Nandi Muzsik
image of Clement Lionne

Created by

Magnetic Button Override in Framer

About the resource

This code override is a piece of cake to tweak in Framer, you just gotta adjust some of the lines in the code.

You can change the "MAX_DISTANCE" value to control how far the element will follow the cursor. You can also change the "damping" and the "stiffness" of the animation.

About the resource

This code override is a piece of cake to tweak in Framer, you just gotta adjust some of the lines in the code.

You can change the "MAX_DISTANCE" value to control how far the element will follow the cursor. You can also change the "damping" and the "stiffness" of the animation.

About the resource

This code override is a piece of cake to tweak in Framer, you just gotta adjust some of the lines in the code.

You can change the "MAX_DISTANCE" value to control how far the element will follow the cursor. You can also change the "damping" and the "stiffness" of the animation.

magnetic override customization

Magnetic override customization.

magnetic override customization

Magnetic override customization.

magnetic override customization

Magnetic override customization.

Code override

Create a code override in your project by going to the assets panel on the left, then scroll down to "code". Click the "+" button to create a new override. Replace the auto-generated code with the code below, and apply it to any element.

Code override

Create a code override in your project by going to the assets panel on the left, then scroll down to "code". Click the "+" button to create a new override. Replace the auto-generated code with the code below, and apply it to any element.

Code override

Create a code override in your project by going to the assets panel on the left, then scroll down to "code". Click the "+" button to create a new override. Replace the auto-generated code with the code below, and apply it to any element.

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

const SPRING_CONFIG = { damping: 100, stiffness: 400 }
const MAX_DISTANCE = 0.5

export const withMagnet = (Component): ComponentType => {
    return (props) => {
        const [isHovered, setIsHovered] = useState(false)
        const x = useMotionValue(0)
        const y = useMotionValue(0)
        const ref = useRef(null)
        const springX = useSpring(x, SPRING_CONFIG)
        const springY = useSpring(y, SPRING_CONFIG)

        useEffect(() => {
            const calculateDistance = (e) => {
                if (ref.current) {
                    const rect = ref.current.getBoundingClientRect()
                    const centerX = rect.left + rect.width / 2
                    const centerY = rect.top + rect.height / 2
                    const distanceX = e.clientX - centerX
                    const distanceY = e.clientY - centerY

                    if (isHovered) {
                        x.set(distanceX * MAX_DISTANCE)
                        y.set(distanceY * MAX_DISTANCE)
                    } else {
                        x.set(0)
                        y.set(0)
                    }
                }
            }

            document.addEventListener("mousemove", calculateDistance)

            return () => {
                document.removeEventListener("mousemove", calculateDistance)
            }
        }, [ref, isHovered])

        return (
            <motion.div
                ref={ref}
                onMouseEnter={() => setIsHovered(true)}
                onMouseLeave={() => setIsHovered(false)}
                style={{
                    x: springX,
                    y: springY,
                    height: props.height || "auto",
                }}
            >
                <Component {...props} />
            </motion.div>
        )
    }
}
import { useState, useEffect, ComponentType, useRef } from "react"
import { motion, useMotionValue, useSpring } from "framer-motion"

const SPRING_CONFIG = { damping: 100, stiffness: 400 }
const MAX_DISTANCE = 0.5

export const withMagnet = (Component): ComponentType => {
    return (props) => {
        const [isHovered, setIsHovered] = useState(false)
        const x = useMotionValue(0)
        const y = useMotionValue(0)
        const ref = useRef(null)
        const springX = useSpring(x, SPRING_CONFIG)
        const springY = useSpring(y, SPRING_CONFIG)

        useEffect(() => {
            const calculateDistance = (e) => {
                if (ref.current) {
                    const rect = ref.current.getBoundingClientRect()
                    const centerX = rect.left + rect.width / 2
                    const centerY = rect.top + rect.height / 2
                    const distanceX = e.clientX - centerX
                    const distanceY = e.clientY - centerY

                    if (isHovered) {
                        x.set(distanceX * MAX_DISTANCE)
                        y.set(distanceY * MAX_DISTANCE)
                    } else {
                        x.set(0)
                        y.set(0)
                    }
                }
            }

            document.addEventListener("mousemove", calculateDistance)

            return () => {
                document.removeEventListener("mousemove", calculateDistance)
            }
        }, [ref, isHovered])

        return (
            <motion.div
                ref={ref}
                onMouseEnter={() => setIsHovered(true)}
                onMouseLeave={() => setIsHovered(false)}
                style={{
                    x: springX,
                    y: springY,
                    height: props.height || "auto",
                }}
            >
                <Component {...props} />
            </motion.div>
        )
    }
}
import { useState, useEffect, ComponentType, useRef } from "react"
import { motion, useMotionValue, useSpring } from "framer-motion"

const SPRING_CONFIG = { damping: 100, stiffness: 400 }
const MAX_DISTANCE = 0.5

export const withMagnet = (Component): ComponentType => {
    return (props) => {
        const [isHovered, setIsHovered] = useState(false)
        const x = useMotionValue(0)
        const y = useMotionValue(0)
        const ref = useRef(null)
        const springX = useSpring(x, SPRING_CONFIG)
        const springY = useSpring(y, SPRING_CONFIG)

        useEffect(() => {
            const calculateDistance = (e) => {
                if (ref.current) {
                    const rect = ref.current.getBoundingClientRect()
                    const centerX = rect.left + rect.width / 2
                    const centerY = rect.top + rect.height / 2
                    const distanceX = e.clientX - centerX
                    const distanceY = e.clientY - centerY

                    if (isHovered) {
                        x.set(distanceX * MAX_DISTANCE)
                        y.set(distanceY * MAX_DISTANCE)
                    } else {
                        x.set(0)
                        y.set(0)
                    }
                }
            }

            document.addEventListener("mousemove", calculateDistance)

            return () => {
                document.removeEventListener("mousemove", calculateDistance)
            }
        }, [ref, isHovered])

        return (
            <motion.div
                ref={ref}
                onMouseEnter={() => setIsHovered(true)}
                onMouseLeave={() => setIsHovered(false)}
                style={{
                    x: springX,
                    y: springY,
                    height: props.height || "auto",
                }}
            >
                <Component {...props} />
            </motion.div>
        )
    }
}

Learn how can one go from 0 to $11.5k with Framer in 60 days.

From no followers, no portfolio, no reputation, to making thousands with a profitable Framer business.

Nandi portrait's background

More resources

More resources

  • Emoji reaction bar with a hand cursor selecting a heart-eyes emoji among various expressive faces on a dark background

    Shiny Cursor Effect in Framer

    Effect

    Emoji reaction bar with a hand cursor selecting a heart-eyes emoji among various expressive faces on a dark background

    Shiny Cursor Effect in Framer

    Effect

  • Graphic showcasing the 'Cursor Trail' component in Framer with a dynamic cursor leaving a trail effect on a starry space background

    Cursor Trail Effect for Framer

    Effect

    Graphic showcasing the 'Cursor Trail' component in Framer with a dynamic cursor leaving a trail effect on a starry space background

    Cursor Trail Effect for Framer

    Effect