Tarjeta con inclinación 3D y brillo
Inclinación según el puntero, brillo especular y capas en profundidad (anillo, esfera y texto) que se separan al inclinar.
Profundidad real
Inclina la tarjeta con el puntero.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { useRef, type CSSProperties, type PointerEvent } from "react";
/** Tarjeta con inclinación 3D, brillo especular que sigue al puntero y capas en profundidad (fondo, forma y texto se separan al inclinar). Vuelve a su sitio con un resorte. React + TypeScript, sin dependencias. */
export type EfectoInclinacionProps = {
title?: string;
text?: string;
max?: number;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gceic-root { box-sizing: border-box; display: inline-block; perspective: 900px; font: 500 15px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
.gceic-root *, .gceic-root *::before, .gceic-root *::after { box-sizing: border-box; }
@media (prefers-reduced-motion: reduce) { .gceic-card { transform: none !important; } }
.gceic-card { --rx: 0deg; --ry: 0deg; --mx: 50%; --my: 50%; position: relative; width: 300px; max-width: 100%; aspect-ratio: 3 / 4; padding: 22px; border-radius: 26px; background: linear-gradient(150deg, #5b7cff, #8a4dff 55%, #ff7ac6); color: #fff; transform-style: preserve-3d; transform: rotateX(var(--rx)) rotateY(var(--ry)); transition: transform .5s cubic-bezier(.16, 1, .3, 1); box-shadow: 0 40px 60px -26px rgba(60, 30, 160, .7); touch-action: pan-y; }
.gceic-card[data-live="true"] { transition-duration: .06s; }
.gceic-glare { position: absolute; inset: 0; border-radius: inherit; background: radial-gradient(240px 240px at var(--mx) var(--my), rgba(255, 255, 255, .5), transparent 60%); mix-blend-mode: soft-light; pointer-events: none; }
.gceic-shape { position: absolute; left: 50%; top: 20%; width: 150px; height: 150px; margin-left: -75px; border-radius: 50%; background: radial-gradient(circle at 35% 30%, #fff6c9, #ffb23f 60%, #ff7a3d); transform: translateZ(60px); box-shadow: 0 24px 30px -12px rgba(120, 40, 0, .5); }
.gceic-ring { position: absolute; left: 50%; top: 20%; width: 230px; height: 230px; margin: -40px 0 0 -115px; border: 3px solid rgba(255, 255, 255, .55); border-radius: 50%; transform: translateZ(25px) rotateX(70deg); }
.gceic-txt { position: absolute; left: 22px; right: 22px; bottom: 22px; transform: translateZ(40px); }
.gceic-txt h3 { margin: 0 0 4px; font: 700 26px/1.05 ui-sans-serif, system-ui, sans-serif; letter-spacing: -.03em; }
.gceic-txt p { margin: 0; opacity: .88; font-size: 14px; }`;
export function EfectoInclinacion({ title = "Profundidad real", text = "Inclina la tarjeta con el puntero.", max = 16, className = "", style }: EfectoInclinacionProps) {
const ref = useRef<HTMLDivElement>(null);
function move(event: PointerEvent<HTMLDivElement>) {
if (event.pointerType === "touch") return;
const el = ref.current!;
const r = el.getBoundingClientRect();
const x = (event.clientX - r.left) / r.width, y = (event.clientY - r.top) / r.height;
el.style.setProperty("--ry", `${(x - 0.5) * max * 2}deg`);
el.style.setProperty("--rx", `${(0.5 - y) * max * 2}deg`);
el.style.setProperty("--mx", `${x * 100}%`);
el.style.setProperty("--my", `${y * 100}%`);
el.dataset.live = "true";
}
function leave() {
const el = ref.current!;
el.style.setProperty("--rx", "0deg");
el.style.setProperty("--ry", "0deg");
delete el.dataset.live;
}
return (
<div className={`gceic-root ${className}`} style={style}>
<style>{CSS}</style>
<div ref={ref} className="gceic-card" onPointerMove={move} onPointerLeave={leave}>
<div className="gceic-ring" aria-hidden="true" />
<div className="gceic-shape" aria-hidden="true" />
<div className="gceic-txt">
<h3>{title}</h3>
<p>{text}</p>
</div>
<div className="gceic-glare" aria-hidden="true" />
</div>
</div>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/efecto-inclinacionEjemplo de uso de Tarjeta con inclinación 3D y brillo
Después de copiar efecto-inclinacion.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { EfectoInclinacion } from "./efecto-inclinacion";
export default function Ejemplo() {
return <EfectoInclinacion title="Ejemplo" />;
}Propiedades de EfectoInclinacion
EfectoInclinacion acepta 5 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
title? | string | Opcional. |
text? | string | Opcional. |
max? | number | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Accesibilidad y rendimiento
El archivo tiene 61 líneas (4 KB) y no necesita @keyframes. Esto es lo que hace Tarjeta con inclinación 3D y brillo por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Expone su estado a tecnologías de apoyo con atributos aria-*.
- Reacciona al puntero con eventos pointer (ratón, lápiz y táctil).
- Es un componente de cliente de Next.js: incluye la directiva "use client".