如何实现CSS动画在页面加载与hover/out时均触发
实现方案
现有基于transition实现的hover动画依赖状态变化触发,要同时支持页面加载自动播放、hover触发两套场景且动画效果完全一致,最优实现是把动画核心逻辑抽离为公共@keyframes关键帧,配合极少量JS处理初始加载的一次性触发即可,全程不需要重复编写动画位移/旋转规则。
核心实现步骤
- 抽离公共动画关键帧:把左右两个圆的位移、翻转效果定义为独立关键帧,桌面端、移动端分别匹配对应位移值,所有场景复用同一段动画定义
- 修正原有CSS笔误:原代码中
transition-timing为错误属性,替换为标准属性transition-timing-function保证缓动效果生效 - 初始加载动画触发:DOM加载完成后给容器添加一次性动画类,动画执行完整的「移入-移出」往返流程,总时长和hover交互时长完全对齐,动画结束后移除该类,不影响后续hover交互
- 保留原有hover交互逻辑:原有基于transition的hover效果不需要大幅修改,和关键帧动画终点状态完全对齐,不会出现样式跳变
完整实现代码
CSS部分
body { margin: 0; padding: 0; } .animation-design { display: flex; justify-content: center; align-items: center; cursor: pointer; position: relative; } .left, .right { width: 215px; height: 215px; border: solid 1.2px #4d4e53; border-radius: 50%; } .left { position: absolute; left: 0; top: 0; } .right { position: absolute; left: 100px; top: 100px; } .animation-design .left, .animation-design .right { transition: all 3s; transition-timing-function: ease-in-out; } /* 公共动画关键帧定义 */ @keyframes moveFlipLeft { to { transform: translateX(100px) rotateY(180deg); } } @keyframes moveFlipRight { to { transform: translateX(-100px) rotateY(180deg); } } /* 页面加载时触发的一次性动画类 */ .load-animate .left { animation: moveFlipLeft 3s ease-in-out; animation-direction: alternate; animation-iteration-count: 2; } .load-animate .right { animation: moveFlipRight 3s ease-in-out; animation-direction: alternate; animation-iteration-count: 2; } .animation-design:hover .left { transform: translateX(100px) rotateY(180deg); } .animation-design:hover .right { transform: translateX(-100px) rotateY(180deg); } /******** 响应式适配 ***********/ @media (max-width: 568px) { .animation-design { width: 132px; height: 132px; } .left, .right { width: 90px; height: 90px; } .right { position: absolute; left: 38px; top: 38px; } /* 移动端匹配对应动画参数 */ @keyframes moveFlipLeft { to { transform: translateX(38px) rotateY(180deg); } } @keyframes moveFlipRight { to { transform: translateX(-38px) rotateY(180deg); } } .animation-design:hover .left { transform: translateX(38px) rotateY(180deg); } .animation-design:hover .right { transform: translateX(-38px) rotateY(180deg); } }
JS部分
无需引入第三方库,仅需添加极短逻辑处理初始加载触发:
document.addEventListener('DOMContentLoaded', () => { const container = document.querySelector('.animation-design') container.classList.add('load-animate') // 动画总时长6s(3s去程+3s回程),跑完移除类名避免干扰后续hover交互 setTimeout(() => { container.classList.remove('load-animate') }, 6000) })
HTML部分
和原有代码完全一致,无需修改:
<body> <div class="animation-design"> <div class="left"></div> <div class="right"></div> </div> </body>
实现说明
该方案下初始加载动画和hover触发的动画参数完全一致,不会出现效果差异;动画结束后移除初始类的操作,能完全避免初始动画和后续hover的transition冲突,鼠标移入移出的交互逻辑和原有效果完全相同。
内容的提问来源于stack exchange,提问作者Fernando Comet
相关产品推荐
相关产品推荐

