3D Card

3D Card component is used to create a 3D card effect.

3d-card-image-case
Whispers of Eternal
In the depths of silence, beauty speaks its most profound truths, echoing through the chambers of our hearts like whispers of eternity.

Usage

Copy the component to your project.

'use client'
 
import { useRef } from 'react'
 
import { cn } from '@/lib/utils'
 
function ThreeDCard({
  children,
  rotateSize = 'medium',
  className,
}: {
  children: React.ReactNode
  rotateSize?: 'small' | 'medium' | 'large' | number
  className?: string
}) {
  const containerRef = useRef<HTMLDivElement>(null)
  const rotateSizeMap = {
    small: 30,
    medium: 20,
    large: 10,
  }
 
  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!containerRef.current) {
      return
    }
    const rotateSizeNumber = typeof rotateSize === 'number' ? rotateSize : rotateSizeMap[rotateSize]
    const { left, top, width, height } = containerRef.current.getBoundingClientRect()
    const x = (e.clientX - left - width / 2) / rotateSizeNumber
    const y = (e.clientY - top - height / 2) / rotateSizeNumber
    containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${-y}deg)`
  }
 
  const handleMouseLeave = () => {
    if (!containerRef.current) {
      return
    }
    containerRef.current.style.transform = 'rotateY(0deg) rotateX(0deg)'
  }
 
  return (
    <div style={{ perspective: '1000px' }} className="flex items-center justify-center">
      <div
        className={cn(
          'relative min-h-[100px] min-w-[100px] rounded-md border border-gray-200 bg-background transition-all duration-200 ease-linear dark:border-gray-900',
          className
        )}
        style={{
          transformStyle: 'preserve-3d',
        }}
        ref={containerRef}
        onMouseMove={handleMouseMove}
        onMouseLeave={handleMouseLeave}
      >
        {children}
      </div>
    </div>
  )
}
 
ThreeDCard.displayName = 'ThreeDCard'
 
export default ThreeDCard

Customize styles

You can override the default styles by setting className. You can also pass rotateSize to adjust the rotation degree.

The rotateSize prop accepts small | medium | large | number

When passing a number, a larger number will result in a smaller rotation angle.