CSS动画需求:页面加载后元素展开,hover时扩展并反向恢复
实现双阶段宽度动画:加载展开 + Hover扩展
刚好做过类似的场景,下面是完整的实现方案,兼顾加载时的初始展开动画,以及hover时的二次扩展/移出恢复效果:
1. 核心思路
- 加载阶段:给每个div绑定专属的关键帧动画,从宽度0过渡到各自的目标宽度,动画结束后保持最终状态
- Hover阶段:定义统一的hover扩展/恢复关键帧,通过
:hover伪类触发扩展动画,鼠标移出时触发恢复动画,同样保持状态
2. 完整代码示例
HTML结构
<div class="box box-21">加载后21vw,hover到30vw</div> <div class="box box-30">加载后30vw,hover到30vw</div> <div class="box box-15">加载后15vw,hover到30vw</div>
CSS样式
/* 基础样式:统一设置高度、背景等,初始宽度为0 */ .box { height: 50px; margin: 10px 0; background: #42b983; overflow: hidden; width: 0; animation-fill-mode: forwards; /* 动画结束后保持最终状态 */ transition: none; /* 避免和动画逻辑冲突 */ } /* -------------------------- 加载阶段关键帧 -------------------------- */ @keyframes grow21 { from { width: 0; } to { width: 21vw; } } @keyframes grow30 { from { width: 0; } to { width: 30vw; } } @keyframes grow15 { from { width: 0; } to { width: 15vw; } } /* 给每个盒子绑定对应的加载动画 */ .box-21 { animation: grow21 0.8s ease-out; } .box-30 { animation: grow30 0.8s ease-out; } .box-15 { animation: grow15 0.8s ease-out; } /* -------------------------- Hover阶段关键帧 -------------------------- */ /* 扩展动画:从当前宽度到固定值30vw */ @keyframes hoverGrow { to { width: 30vw; } } /* 恢复动画:从30vw回到各自加载后的宽度 */ @keyframes shrinkBack21 { to { width: 21vw; } } @keyframes shrinkBack30 { to { width: 30vw; } } @keyframes shrinkBack15 { to { width: 15vw; } } /* Hover触发扩展 */ .box:hover { animation: hoverGrow 0.3s ease-out forwards; } /* 鼠标移出触发恢复 */ .box-21:not(:hover) { animation: shrinkBack21 0.3s ease-out forwards; } .box-30:not(:hover) { animation: shrinkBack30 0.3s ease-out forwards; } .box-15:not(:hover) { animation: shrinkBack15 0.3s ease-out forwards; }
3. 关键细节说明
- 使用
animation-fill-mode: forwards是核心,确保动画结束后元素保持关键帧的最终状态,而不是回到初始样式 - 每个盒子的恢复动画要对应它加载后的目标宽度,这样移出鼠标时能精准回到初始展开后的状态
- 可以根据需求调整动画的
duration(时长)和timing-function(缓动函数),比如ease-out会让动画结尾更平滑 - 如果所有hover后的固定值都是同一个(比如都是30vw),那扩展动画可以共用一个关键帧,不用每个都单独定义
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

