纯css悬停倾斜需父容器设perspective、卡片设transform-style:preserve-3d和transform-origin:center center,用:hover预设rotatex/rotatey(±3°~8°)配合ease-out过渡;真鼠标跟随必须js监听mousemove动态计算角度。

为什么直接用 transform: rotateX() 和 rotateY() 悬停会“翻车”
因为纯 rotateX() 或 rotateY() 会让卡片绕自身坐标轴旋转,视觉上像“翻页”或“仰头”,不是自然的 3D 倾斜;真正要的是鼠标靠近哪边,卡片就向反方向微倾——这需要结合 perspective、transform-origin 和动态计算的旋转角度,否则悬停后元素会突然跳变、消失或失真。
-
perspective必须加在父容器(如卡片外层 wrapper),不能只加在卡片自身,否则 3D 效果不生效 - 默认
transform-origin: center会导致旋转中心僵硬,实际需设为center center并配合transform-style: preserve-3d - 仅靠 CSS 无法读取鼠标坐标,所以纯 CSS 实现“跟随鼠标倾斜”必须用
rotateX()+rotateY()配合transition做固定角度切换,而非实时追踪
纯 CSS 实现可落地的悬停倾斜(非实时追踪版)
适合大多数展示型卡片,用 :hover 触发预设的 rotateX 和 rotateY 组合,配合 transform-origin 控制倾斜支点:
.card {
width: 300px;
height: 200px;
background: #fff;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
/* 关键:启用 3D 渲染上下文 */
transform-style: preserve-3d;
transition: transform 0.3s ease-out;
}
<p>.card:hover {
/<em> 向上倾斜 + 向左倾斜 → 模拟鼠标在右下角时的反向响应 </em>/
transform: rotateX(-5deg) rotateY(5deg);
}</p><p>/<em> 父容器必须设 perspective,否则 rotateX/Y 无 3D 感 </em>/
.card-wrapper {
perspective: 1000px;
}</p>
- 角度建议控制在 ±3°~±8° 之间,超过 10° 易产生眩晕感
-
transition-timing-function推荐用ease-out或cubic-bezier(0.17, 0.67, 0.83, 0.67),避免机械式线性过渡 - 若卡片内有文字或子元素,确保它们没设置
transform: translateZ(...)冲突值,否则会错位
想让倾斜“跟着鼠标走”?必须用 JavaScript 补足
CSS 本身无法获取鼠标相对元素的位置,所以真正的“鼠标驱动 3D 倾斜”需要监听 mousemove,动态计算 rotateX 和 rotateY 值并写入 style.transform:
const card = document.querySelector('.card');
card.addEventListener('mousemove', (e) => {
const rect = card.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
// 距离中心越远,倾斜越大(最大 ±12°)
const rotateY = (x - centerX) / centerX * 12;
const rotateX = (centerY - y) / centerY * 12;
card.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
});
- 注意:必须在
card上同时设置transform-style: preserve-3d和父级perspective - 移动端无
mousemove,需额外处理touchmove,且触摸点坐标要用e.touches[0] - 高频触发易卡顿,建议用
requestAnimationFrame节流,不要直接在事件里写style.transform
容易被忽略的兼容性与性能坑
这个效果在 Safari 和旧版 Chrome 上表现差异大,尤其涉及 preserve-3d 时:
- iOS Safari 对
transform-style: preserve-3d支持不稳定,某些版本下子元素会“扁平化”,解决办法是给卡片加backface-visibility: hidden - Android WebView 中,若卡片含
border-radius+transform,边缘可能锯齿,加-webkit-backface-visibility: hidden可缓解 - 大量卡片同时启用 3D transform 会触发 GPU 渲染,但若页面已有其他动画(如
position: sticky或频繁重排),可能引发掉帧,建议用will-change: transform提前提示(仅对 hover 卡片)
真实项目中,先跑通基础 rotateX/rotateY + perspective 组合,再决定是否上 JS 动态倾斜——多数场景下固定角度 hover 已足够传达交互意图,不必为“更真实”增加维护成本和兼容风险。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











