3D Hover Override

Effect

3D Hover Override

This is a 3D hover code override that you can apply to any element to achieve a pleasing 3D hover effect. For an enhanced effect, there's an additional override in the file applicable to a 'shine' layer. This will make the shine follow the cursor, producing an illusion of light shining on the card when you hover over it.

image of Nandi Muzsik

Created by

3d hover override in Framer
3d hover override in Framer
3d hover override in Framer

Related Lesson

Related Lesson

Related Lesson

About the resource

The file contains the necessary override for the 3D hover effect, which should be applied to the card. It also includes an override that makes the layer follow the cursor, which should be applied to the 'shine' layer.

Watch the tutorial video for detailed instructions on how to utilize this effect.

Code override for 3D hover

You can also copy the code for the 3D hover override and create the override from scratch in your project.

About the resource

The file contains the necessary override for the 3D hover effect, which should be applied to the card. It also includes an override that makes the layer follow the cursor, which should be applied to the 'shine' layer.

Watch the tutorial video for detailed instructions on how to utilize this effect.

Code override for 3D hover

You can also copy the code for the 3D hover override and create the override from scratch in your project.

About the resource

The file contains the necessary override for the 3D hover effect, which should be applied to the card. It also includes an override that makes the layer follow the cursor, which should be applied to the 'shine' layer.

Watch the tutorial video for detailed instructions on how to utilize this effect.

Code override for 3D hover

You can also copy the code for the 3D hover override and create the override from scratch in your project.

// © Framer University. All rights reserved.

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

// Learn more: https://www.framer.com/docs/guides/overrides/

//Spring animation parameters
const spring = {
    type: "spring",
    stiffness: 300,
    damping: 30,
}

/**
 * Based on the code created by Joshua Guo
 *
 * @framerSupportedLayoutWidth fixed
 * @framerSupportedLayoutHeight fixed
 */

export function with3D(Component): ComponentType {
    return (props) => {
        const [rotateXaxis, setRotateXaxis] = useState(0)
        const [rotateYaxis, setRotateYaxis] = useState(0)
        const ref = useRef(null)

        const handleMouseMove = (event) => {
            const element = ref.current
            const elementRect = element.getBoundingClientRect()
            const elementWidth = elementRect.width
            const elementHeight = elementRect.height
            const elementCenterX = elementWidth / 2
            const elementCenterY = elementHeight / 2
            const mouseX = event.clientY - elementRect.y - elementCenterY
            const mouseY = event.clientX - elementRect.x - elementCenterX
            const degreeX = (mouseX / elementWidth) * -20 //The number is the rotation factor
            const degreeY = (mouseY / elementHeight) * -20 //The number is the rotation factor
            setRotateXaxis(degreeX)
            setRotateYaxis(degreeY)
        }

        const handleMouseEnd = () => {
            setRotateXaxis(0)
            setRotateYaxis(0)
        }

        const dx = useSpring(0, spring)
        const dy = useSpring(0, spring)

        useEffect(() => {
            dx.set(-rotateXaxis)
            dy.set(rotateYaxis)
        }, [rotateXaxis, rotateYaxis])

        return (
            <motion.div
                transition={spring}
                style={{
                    perspective: "1200px",
                    transformStyle: "preserve-3d",
                    width: `${props.width}`,
                    height: `${props.height}`,
                }}
            >
                <motion.div
                    ref={ref}
                    whileHover={{ scale: 1.1 }} //Change the scale of zooming in when hovering
                    onMouseMove={handleMouseMove}
                    onMouseLeave={handleMouseEnd}
                    transition={spring}
                    style={{
                        width: "100%",
                        height: "100%",
                        rotateX: dx,
                        rotateY: dy,
                    }}
                >
                    <div
                        style={{
                            perspective: "1200px",
                            transformStyle: "preserve-3d",
                            width: "100%",
                            height: "100%",
                        }}
                    >
                        <motion.div
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Front"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                        <motion.div
                            initial={{ rotateY: 180 }}
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                zIndex: 0,
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Back"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                    </div>
                </motion.div>
            </motion.div>
        )
    }
}

// © Framer University. All rights reserved.

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

// Learn more: https://www.framer.com/docs/guides/overrides/

//Spring animation parameters
const spring = {
    type: "spring",
    stiffness: 300,
    damping: 30,
}

/**
 * Based on the code created by Joshua Guo
 *
 * @framerSupportedLayoutWidth fixed
 * @framerSupportedLayoutHeight fixed
 */

export function with3D(Component): ComponentType {
    return (props) => {
        const [rotateXaxis, setRotateXaxis] = useState(0)
        const [rotateYaxis, setRotateYaxis] = useState(0)
        const ref = useRef(null)

        const handleMouseMove = (event) => {
            const element = ref.current
            const elementRect = element.getBoundingClientRect()
            const elementWidth = elementRect.width
            const elementHeight = elementRect.height
            const elementCenterX = elementWidth / 2
            const elementCenterY = elementHeight / 2
            const mouseX = event.clientY - elementRect.y - elementCenterY
            const mouseY = event.clientX - elementRect.x - elementCenterX
            const degreeX = (mouseX / elementWidth) * -20 //The number is the rotation factor
            const degreeY = (mouseY / elementHeight) * -20 //The number is the rotation factor
            setRotateXaxis(degreeX)
            setRotateYaxis(degreeY)
        }

        const handleMouseEnd = () => {
            setRotateXaxis(0)
            setRotateYaxis(0)
        }

        const dx = useSpring(0, spring)
        const dy = useSpring(0, spring)

        useEffect(() => {
            dx.set(-rotateXaxis)
            dy.set(rotateYaxis)
        }, [rotateXaxis, rotateYaxis])

        return (
            <motion.div
                transition={spring}
                style={{
                    perspective: "1200px",
                    transformStyle: "preserve-3d",
                    width: `${props.width}`,
                    height: `${props.height}`,
                }}
            >
                <motion.div
                    ref={ref}
                    whileHover={{ scale: 1.1 }} //Change the scale of zooming in when hovering
                    onMouseMove={handleMouseMove}
                    onMouseLeave={handleMouseEnd}
                    transition={spring}
                    style={{
                        width: "100%",
                        height: "100%",
                        rotateX: dx,
                        rotateY: dy,
                    }}
                >
                    <div
                        style={{
                            perspective: "1200px",
                            transformStyle: "preserve-3d",
                            width: "100%",
                            height: "100%",
                        }}
                    >
                        <motion.div
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Front"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                        <motion.div
                            initial={{ rotateY: 180 }}
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                zIndex: 0,
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Back"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                    </div>
                </motion.div>
            </motion.div>
        )
    }
}

// © Framer University. All rights reserved.

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

// Learn more: https://www.framer.com/docs/guides/overrides/

//Spring animation parameters
const spring = {
    type: "spring",
    stiffness: 300,
    damping: 30,
}

/**
 * Based on the code created by Joshua Guo
 *
 * @framerSupportedLayoutWidth fixed
 * @framerSupportedLayoutHeight fixed
 */

export function with3D(Component): ComponentType {
    return (props) => {
        const [rotateXaxis, setRotateXaxis] = useState(0)
        const [rotateYaxis, setRotateYaxis] = useState(0)
        const ref = useRef(null)

        const handleMouseMove = (event) => {
            const element = ref.current
            const elementRect = element.getBoundingClientRect()
            const elementWidth = elementRect.width
            const elementHeight = elementRect.height
            const elementCenterX = elementWidth / 2
            const elementCenterY = elementHeight / 2
            const mouseX = event.clientY - elementRect.y - elementCenterY
            const mouseY = event.clientX - elementRect.x - elementCenterX
            const degreeX = (mouseX / elementWidth) * -20 //The number is the rotation factor
            const degreeY = (mouseY / elementHeight) * -20 //The number is the rotation factor
            setRotateXaxis(degreeX)
            setRotateYaxis(degreeY)
        }

        const handleMouseEnd = () => {
            setRotateXaxis(0)
            setRotateYaxis(0)
        }

        const dx = useSpring(0, spring)
        const dy = useSpring(0, spring)

        useEffect(() => {
            dx.set(-rotateXaxis)
            dy.set(rotateYaxis)
        }, [rotateXaxis, rotateYaxis])

        return (
            <motion.div
                transition={spring}
                style={{
                    perspective: "1200px",
                    transformStyle: "preserve-3d",
                    width: `${props.width}`,
                    height: `${props.height}`,
                }}
            >
                <motion.div
                    ref={ref}
                    whileHover={{ scale: 1.1 }} //Change the scale of zooming in when hovering
                    onMouseMove={handleMouseMove}
                    onMouseLeave={handleMouseEnd}
                    transition={spring}
                    style={{
                        width: "100%",
                        height: "100%",
                        rotateX: dx,
                        rotateY: dy,
                    }}
                >
                    <div
                        style={{
                            perspective: "1200px",
                            transformStyle: "preserve-3d",
                            width: "100%",
                            height: "100%",
                        }}
                    >
                        <motion.div
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Front"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                        <motion.div
                            initial={{ rotateY: 180 }}
                            transition={spring}
                            style={{
                                width: "100%",
                                height: "100%",
                                zIndex: 0,
                                backfaceVisibility: "hidden",
                                position: "absolute",
                            }}
                        >
                            <Component
                                {...props}
                                variant="Back"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                }}
                            />
                        </motion.div>
                    </div>
                </motion.div>
            </motion.div>
        )
    }
}

Code override for cursor follow

You can also copy the code for the cursor follow override and create the override from scratch in your project.

Code override for cursor follow

You can also copy the code for the cursor follow override and create the override from scratch in your project.

Code override for cursor follow

You can also copy the code for the cursor follow override and create the override from scratch in your project.

// © Framer University. All rights reserved.

import type { ComponentType } from "react"
import { useRef, useState } from "react"
import { useEffect } from "react"
import { useSpring, animated } from "react-spring"

export function withCursorFollow(Component): ComponentType {
    return (props) => {
        const ref = useRef(null)
        const [isHovering, setIsHovering] = useState(false)
        const [originalPosition, setOriginalPosition] = useState({
            left: 0,
            top: 0,
        })
        const [centerPosition, setCenterPosition] = useState({
            left: 0,
            top: 0,
        })
        const springProps = useSpring({
            left: isHovering ? originalPosition.left : centerPosition.left,
            top: isHovering ? originalPosition.top : centerPosition.top,
            config: { mass: 1, tension: 170, friction: 26 },
        })

        useEffect(() => {
            if (!ref.current) return
            const buttonRect = ref.current.getBoundingClientRect()
            const elementRect = ref.current.getBoundingClientRect()
            setCenterPosition({
                left: buttonRect.width / 2 - elementRect.width / 2,
                top: buttonRect.height / 2 - elementRect.height / 2,
            })

            const handleMouseMove = (e) => {
                if (!ref.current) return
                if (e.target.closest("button")) {
                    setIsHovering(true)
                    const buttonRect = e.target.getBoundingClientRect()
                    const elementRect = ref.current.getBoundingClientRect()
                    setOriginalPosition({
                        left:
                            e.clientX - buttonRect.left - elementRect.width / 2,
                        top:
                            e.clientY - buttonRect.top - elementRect.height / 2,
                    })
                    setCenterPosition({
                        left: buttonRect.width / 2 - elementRect.width / 2,
                        top: buttonRect.height / 2 - elementRect.height / 2,
                    })
                } else {
                    setIsHovering(false)
                }
            }

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

        return (
            <animated.div
                ref={ref}
                style={{
                    position: "absolute",
                    pointerEvents: "none",
                    left: springProps.left,
                    top: springProps.top,
                }}
            >
                <Component {...props} />
            </animated.div>
        )
    }
}

// © Framer University. All rights reserved.

import type { ComponentType } from "react"
import { useRef, useState } from "react"
import { useEffect } from "react"
import { useSpring, animated } from "react-spring"

export function withCursorFollow(Component): ComponentType {
    return (props) => {
        const ref = useRef(null)
        const [isHovering, setIsHovering] = useState(false)
        const [originalPosition, setOriginalPosition] = useState({
            left: 0,
            top: 0,
        })
        const [centerPosition, setCenterPosition] = useState({
            left: 0,
            top: 0,
        })
        const springProps = useSpring({
            left: isHovering ? originalPosition.left : centerPosition.left,
            top: isHovering ? originalPosition.top : centerPosition.top,
            config: { mass: 1, tension: 170, friction: 26 },
        })

        useEffect(() => {
            if (!ref.current) return
            const buttonRect = ref.current.getBoundingClientRect()
            const elementRect = ref.current.getBoundingClientRect()
            setCenterPosition({
                left: buttonRect.width / 2 - elementRect.width / 2,
                top: buttonRect.height / 2 - elementRect.height / 2,
            })

            const handleMouseMove = (e) => {
                if (!ref.current) return
                if (e.target.closest("button")) {
                    setIsHovering(true)
                    const buttonRect = e.target.getBoundingClientRect()
                    const elementRect = ref.current.getBoundingClientRect()
                    setOriginalPosition({
                        left:
                            e.clientX - buttonRect.left - elementRect.width / 2,
                        top:
                            e.clientY - buttonRect.top - elementRect.height / 2,
                    })
                    setCenterPosition({
                        left: buttonRect.width / 2 - elementRect.width / 2,
                        top: buttonRect.height / 2 - elementRect.height / 2,
                    })
                } else {
                    setIsHovering(false)
                }
            }

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

        return (
            <animated.div
                ref={ref}
                style={{
                    position: "absolute",
                    pointerEvents: "none",
                    left: springProps.left,
                    top: springProps.top,
                }}
            >
                <Component {...props} />
            </animated.div>
        )
    }
}

// © Framer University. All rights reserved.

import type { ComponentType } from "react"
import { useRef, useState } from "react"
import { useEffect } from "react"
import { useSpring, animated } from "react-spring"

export function withCursorFollow(Component): ComponentType {
    return (props) => {
        const ref = useRef(null)
        const [isHovering, setIsHovering] = useState(false)
        const [originalPosition, setOriginalPosition] = useState({
            left: 0,
            top: 0,
        })
        const [centerPosition, setCenterPosition] = useState({
            left: 0,
            top: 0,
        })
        const springProps = useSpring({
            left: isHovering ? originalPosition.left : centerPosition.left,
            top: isHovering ? originalPosition.top : centerPosition.top,
            config: { mass: 1, tension: 170, friction: 26 },
        })

        useEffect(() => {
            if (!ref.current) return
            const buttonRect = ref.current.getBoundingClientRect()
            const elementRect = ref.current.getBoundingClientRect()
            setCenterPosition({
                left: buttonRect.width / 2 - elementRect.width / 2,
                top: buttonRect.height / 2 - elementRect.height / 2,
            })

            const handleMouseMove = (e) => {
                if (!ref.current) return
                if (e.target.closest("button")) {
                    setIsHovering(true)
                    const buttonRect = e.target.getBoundingClientRect()
                    const elementRect = ref.current.getBoundingClientRect()
                    setOriginalPosition({
                        left:
                            e.clientX - buttonRect.left - elementRect.width / 2,
                        top:
                            e.clientY - buttonRect.top - elementRect.height / 2,
                    })
                    setCenterPosition({
                        left: buttonRect.width / 2 - elementRect.width / 2,
                        top: buttonRect.height / 2 - elementRect.height / 2,
                    })
                } else {
                    setIsHovering(false)
                }
            }

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

        return (
            <animated.div
                ref={ref}
                style={{
                    position: "absolute",
                    pointerEvents: "none",
                    left: springProps.left,
                    top: springProps.top,
                }}
            >
                <Component {...props} />
            </animated.div>
        )
    }
}

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

Framer Navigator

Learn the fundamentals of Framer for free.

Build your ideas with ease by learning the basics of website building with Framer.

Nandi portrait's background
Nandi's portrait

More resources

More resources

    Show Once Code Override for Framer

    Show Once Code Override for Framer

    Effect

    Show Once Code Override for Framer

    Show Once Code Override for Framer

    Effect

    Show Once Code Override for Framer

    Show Once Code Override for Framer

    Effect

    2 Types of Horizontal Scrolling in Framer

    2 Types of Horizontal Scrolling Effect in Framer

    Effect

    2 Types of Horizontal Scrolling in Framer

    2 Types of Horizontal Scrolling Effect in Framer

    Effect

    2 Types of Horizontal Scrolling in Framer

    2 Types of Horizontal Scrolling Effect in Framer

    Effect