Squash Text
On hover, characters squash and stretch in a staggered sequence using framer-motion variants propagation.
Use and inspectUse this when the motion supports the surrounding content. Connect callbacks and state to your app, keep the reset preview as a local demonstration, and add a reduced-motion fallback for movement or looping. The preview is synthetic; it does not call a backend.Next: inspect the source below and replace the demo inputs with your own data.
Squash TextOn hover, characters squash and stretch in a staggered sequence using framer-motion variants propagation.
"use client";
import { motion, type Variants } from "framer-motion";
type SquashTextProps = {
text: string;
};
const containerVariants: Variants = {
rest: {},
hover: { transition: { staggerChildren: 0.05 } },
};
const charVariants: Variants = {
rest: { scaleY: 1, scaleX: 1 },
hover: {
scaleY: [1, 0.45, 1.3, 1],
scaleX: [1, 1.3, 0.85, 1],
transition: { duration: 0.45, ease: "easeInOut" },
},
};
export function SquashText({ text }: SquashTextProps) {
const chars = text.split("");
return (
<motion.span
className="mp-squash-text"
variants={containerVariants}
initial="rest"
whileHover="hover"
style={{ display: "inline-flex", cursor: "default" }}
aria-label={text}
>
{chars.map((char, i) => (
<motion.span
key={i}
variants={charVariants}
className="mp-squash-text-char"
style={{ display: "inline-block", transformOrigin: "50% 100%" }}
>
{char === " " ? "\u00A0" : char}
</motion.span>
))}
</motion.span>
);
}Install
npm install framer-motionProps
| Prop | Type | Default | Description |
|---|---|---|---|
| textrequired | string | — | Text to squash on hover |