
本文介绍如何在 CSS 中实现“悬停时上移子元素,点击父容器时保持该位移并叠加摇晃动画”的效果,避免因 transform 覆盖导致位移丢失,并提供兼容性好、语义清晰的解决方案。
本文介绍如何在 css 中实现“悬停时上移子元素,点击父容器时保持该位移并叠加摇晃动画”的效果,避免因 `transform` 覆盖导致位移丢失,并提供兼容性好、语义清晰的解决方案。
要实现在 .parent:hover 时让 .child 向上平移 10px,并在 .parent:active 点击瞬间持续保持该位移的同时执行摇晃动画(shake),关键在于理解 CSS transform 的覆盖机制:当 :active 规则中仅声明 animation,而未显式重设 translateY(-10px),浏览器会将 transform 属性重置为初始值(即 none),从而导致位移“闪退”。
✅ 正确做法是:在动画关键帧中显式组合变换,或利用独立的 rotate 属性(CSS Level 4)避免干扰 translateY。推荐以下两种稳定方案:
✅ 方案一:在 @keyframes 中完整声明复合 transform
.parent {
width: 100px;
height: 100px;
background-color: red;
display: flex;
justify-content: center;
align-items: center;
}
.child {
width: 50px;
height: 50px;
background-color: green;
transition: transform 1s ease; /* 显式过渡 transform */
}
.parent:hover .child {
transform: translateY(-10px);
}
.parent:active .child {
animation: shake 1s forwards; /* 添加 forwards 保持最终帧状态 */
}
@keyframes shake {
0% {
transform: translateY(-10px) rotate(-10deg);
}
25% {
transform: translateY(-10px) rotate(10deg);
}
50% {
transform: translateY(-10px) rotate(-10deg);
}
75% {
transform: translateY(-10px) rotate(10deg);
}
100% {
transform: translateY(-10px) rotate(0deg);
}
}
⚠️ 注意事项:
- 必须添加
animation-fill-mode: forwards(简写为forwards),否则动画结束后transform会恢复到:active规则前的状态(即 hover 结束后的值或初始值);- 所有关键帧均需包含
translateY(-10px),确保位移不被覆盖;transition应限定为transform,避免与其他属性冲突。
✅ 方案二(现代浏览器优先):使用独立 rotate 属性(无需拼接 transform)
@keyframes shake {
0% { rotate: -10deg; }
50% { rotate: 10deg; }
100% { rotate: 0deg; }
}
此方式将旋转与位移解耦——translateY(-10px) 由 hover 控制,rotate 由动画独立驱动,天然互不干扰。但需注意:rotate 属于 CSS Transforms Level 2,目前主流浏览器(Chrome 104+, Firefox 95+, Safari 15.4+)已支持,旧版需回退至方案一。
? 补充建议
- 若需支持长按后持续高亮(如移动端),可结合
:focus-within或 JavaScript 添加临时类(如.clicked),提升可控性; - 避免在
:active中设置transform: none或其他覆盖值; - 动画时长与缓动函数建议匹配交互节奏(如
cubic-bezier(0.34, 1.56, 0.64, 1)增强动感)。
通过合理组合 transform 值或采用模块化变换属性,即可优雅实现“悬停定位 + 点击动画”的复合交互,兼顾表现力与可维护性。










