# 悬停上浮 Hover Lift > 鼠标放到卡片上,卡片往上浮一点、影子变深,图片微微放大。 分类:动效 · 角色:基础(手感,哪里都能用、不抢眼) [全部组件和流程](https://www.dachuiai.com/llms.txt) · [动效选型规则](https://www.dachuiai.com/guides/motion.md) ## 给 AI:用户把这个组件发给了你 1. 先看用户的项目:框架、页面类型、现在的风格、手机还是电脑为主。 2. 对照下面的「适合 / 不适合」判断合不合适。不合适就直接说,并从[动效选型规则](https://www.dachuiai.com/guides/motion.md)或[全部组件](https://www.dachuiai.com/llms.txt)里另挑一个。 3. 合适就按「装进项目」装好,示例里的文字和图片换成用户自己的。 4. 告诉用户用了什么、放在哪个文件、以后想改快慢、颜色、大小改哪个参数。 ## 什么时候用 - 适合:所有能点的卡片:商品卡、文章卡、作品卡。 - 不适合:不能点的卡片(会让人以为能点)。 - 适合的网站:官网、本地小店、电商、作品集、SaaS、后台、内容站、活动页 - 放在:卡片 - 手机上:没效果:手机上没有悬停,不影响点击。 - 性能代价:低:纯 CSS。 - 常搭配:[错峰 Stagger](https://www.dachuiai.com/c/stagger.md)、[滚动出现 Scroll Reveal](https://www.dachuiai.com/c/scroll-reveal.md)、[聚光 Spotlight](https://www.dachuiai.com/c/spotlight.md) ## 装进项目 - 写法:React 18 以上 + TypeScript + Tailwind CSS v4,一个文件就能用,不引用别的组件。 - 依赖:`npm i lucide-react` - 文件:原样存成 `hover-lift.tsx`(比如 `src/components/hover-lift.tsx`)。能跑命令就下载[原文](https://www.dachuiai.com/code/hover-lift.tsx),比手抄准:`curl -fsSL -o src/components/hover-lift.tsx https://www.dachuiai.com/code/hover-lift.tsx`(Windows 写 `curl.exe`)。下载完看一眼第一行是 `import`,不是网页。 - 导出:`LiftCard` 是可以直接用的部分;最后的 `export default` 是演示示例,只作参考。 - 图片:示例用了本站的 [/tex/s5.jpg](https://www.dachuiai.com/tex/s5.jpg)、[/tex/s6.jpg](https://www.dachuiai.com/tex/s6.jpg)、[/tex/s2.jpg](https://www.dachuiai.com/tex/s2.jpg)。换成用户自己的图;只想先看效果,可以从本站同样的路径下载,放进项目的 public 目录。 - 注意:浅色网站传 tone="light"。别的颜色在 className 里改变量,比如 [--lift-bg:#FFF8F0] [--lift-line:#E7D8C6];直接写 bg-、border- 颜色类会和默认颜色抢,不一定生效。用 React Router 或 Next.js 的 Link 时传 as={Link},to、href 照常写;不跳转、只点开弹窗的卡片用 as="button"。 - Next.js(有 app 文件夹):文件第一行加 `'use client';`。 - 用 JavaScript 不用 TypeScript:Vite 和 Next.js 都能直接用 .tsx 文件;也可以删掉类型标注,改名 .jsx。 - 没有 Tailwind:先装 Tailwind CSS v4(Vite 项目 `npm i tailwindcss @tailwindcss/vite`,vite 配置的 plugins 里加 `tailwindcss()`,入口引入的那个 CSS 文件(一般是 `src/index.css`)第一行写 `@import "tailwindcss";`),或者把类名改写成项目用的样式。 - 已经装了 Tailwind v3:别为了一个组件升级。类名大多通用,少数 v4 写法要换,比如焦点框 `outline-2` 在 v3 里要写成 `outline outline-2`。 - 不是 React(Vue、Svelte、小程序、纯 HTML):照着代码的做法改写,时长、曲线、参数保持一样。Wix、有赞这类建站平台装不进代码,告诉用户去平台自带的动效设置里找。 ## 参数 | 参数 | 默认值 | 作用 | | --- | --- | --- | | `as` | | 渲染成什么元素,默认 a,用 React Router 或 Next.js 的 Link 时传 as={Link}(to、href 照常写),也可以 as="button" | | `tone` | `'dark'` | dark 深色底(默认)/ light 浅色底 | | `className` | `''` | 加在最外层的类名,用来调大小、位置、间距 | | `children` | | 包在里面的内容 | ## 你可以说 > 商品卡片加 Hover Lift 悬停上浮:鼠标放上去卡片往上浮一点、影子变深,图片微微放大。 ## 完整代码 ```tsx import type {ComponentProps, ElementType, ReactNode} from 'react'; import {Backpack, Star, Tent, Thermometer} from 'lucide-react'; /* --------------------------------------------------------------- * HoverLift 悬停上浮 * 鼠标放到卡片上,卡片微微浮起来、影子变深,告诉你这一块能点。 * 键盘 Tab 到卡片上时也一样浮起。 * tone:dark 深色底(默认)/ light 浅色底。别的颜色在 className 里改变量: * [--lift-bg:#FFF8F0] 底色、[--lift-line:…] 边框、[--lift-line-hover:…] 悬停边框、[--lift-shadow:…] 悬停影子。 * as:渲染成什么元素,默认 a,用 React Router 或 Next.js 的 Link 时传 as={Link}(to、href 照常写),也可以 as="button" * ------------------------------------------------------------- */ const TONE = { dark: 'bg-[color:var(--lift-bg,#14141B)] border-[color:var(--lift-line,rgb(255_255_255/.1))] hover:border-[color:var(--lift-line-hover,rgb(255_255_255/.25))] hover:shadow-[var(--lift-shadow,0_32px_60px_-18px_rgba(0,0,0,.9))] focus-visible:shadow-[var(--lift-shadow,0_32px_60px_-18px_rgba(0,0,0,.9))]', light: 'bg-[color:var(--lift-bg,#FFFFFF)] border-[color:var(--lift-line,rgb(24_24_27/.08))] hover:border-[color:var(--lift-line-hover,rgb(24_24_27/.16))] hover:shadow-[var(--lift-shadow,0_24px_48px_-20px_rgba(24,24,27,.28))] focus-visible:shadow-[var(--lift-shadow,0_24px_48px_-20px_rgba(24,24,27,.28))]', }; type LiftCardProps = {as?: T; tone?: keyof typeof TONE; className?: string; children: ReactNode} & Omit, 'as' | 'className' | 'children'>; export function LiftCard({as, tone = 'dark', className = '', children, ...rest}: LiftCardProps) { const Tag: ElementType = as ?? 'a'; return ( {children} ); } /* ---------------- 示例:三张商品卡 ---------------- */ const GOODS = [ ['露营帐篷', '¥899', '/tex/s5.jpg', Tent, '4.8 · 已售 2k'], ['徒步背包', '¥459', '/tex/s6.jpg', Backpack, '4.9 · 已售 3k'], ['保温水壶', '¥129', '/tex/s2.jpg', Thermometer, '4.7 · 已售 5k'], ] as const; export default function HoverLiftDemo() { return (
{GOODS.map(([name, price, img, Icon, meta]) => (
{name}
{meta}
{price}
))}
); } ```