如何实现div内图片hover时上移循环露出的悬停交互效果
悬停上滑切换效果实现方案
效果通用名称
这类动效没有统一的官方标准命名,前端业内通常称其为悬停上滑切换效果,部分资料也会按实现逻辑称其为溢出裁剪位移动画。你提到的目标站点按钮、菜单项的悬停动效,核心实现逻辑和这个完全一致,只是额外增加了斜切变形、缓动曲线微调的细节。
原有代码问题
- 事件名写法错误:JS监听鼠标移入事件的事件名是
mouseover,你写的onmouseover多了on前缀还带多余空格,且没有编写鼠标移出后的状态还原逻辑 - 结构缺失:要实现“当前元素上移移出、相同元素从下方补入”的效果,每个logo容器内需要放置2份相同的logo素材,外层容器必须做溢出隐藏,否则移动过程中的元素会外露
- 动画逻辑缺失:仅添加类名没有编写对应的CSS过渡、位移规则,无法触发动效
正确实现方案
这个效果不需要编写JavaScript逻辑,纯CSS即可实现,性能比JS事件监听更好,交互稳定性更高。
实现原理
- 给每个logo外层容器设置固定高度,添加
overflow: hidden属性,把超出容器范围的内容全部裁剪,作为动画的可视窗口 - 容器内放置2份完全相同的logo,默认状态下第一份显示在容器可视区域,第二份定位在容器正下方不可见
- 鼠标悬停时,两份logo同时向上做位移:第一份向上移出容器可视范围,第二份向上移动到第一份原来的位置,搭配平滑过渡动画即可实现目标效果
完整代码
CSS样式(替换你原有logo相关样式即可)
.logos-container{ background: #ddd; } .logos-container .client-logo{ width: 8rem; height: 3rem; /* 按照logo实际高度调整,必须设置固定高度 */ position: relative; overflow: hidden; } .logos-container .client-logo img{ width: 100%; height: 100%; object-fit: contain; position: absolute; left: 0; /* 缓动曲线和动画时长可自行调整,当前参数和目标站点效果接近 */ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); } /* 默认状态:第一层logo在可视区,第二层在容器下方 */ .logos-container .client-logo img:nth-child(1){ top: 0; transform: translateY(0); } .logos-container .client-logo img:nth-child(2){ top: 0; transform: translateY(100%); } /* 悬停状态:两层logo同时上移100%,完成切换 */ .logos-container .client-logo:hover img:nth-child(1){ transform: translateY(-100%); } .logos-container .client-logo:hover img:nth-child(2){ transform: translateY(0); } .round-logo{ width: 5rem !important; } .rect-logo{ width: 14rem !important; }
HTML结构调整
每个.client-logo容器内需要放2份相同的logo图片,修改后结构如下:
<div class="container logos-container d-flex justify-content-between align-items-center flex-wrap px-4 py-3"> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/nasa-6.svg" alt="NASA"> <img src="https://cdn.worldvectorlogo.com/logos/nasa-6.svg" alt="NASA"> </div> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/microsoft.svg" alt="Microsoft"> <img src="https://cdn.worldvectorlogo.com/logos/microsoft.svg" alt="Microsoft"> </div> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/ibm.svg" alt="IBM"> <img src="https://cdn.worldvectorlogo.com/logos/ibm.svg" alt="IBM"> </div> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/dell-computer.svg" alt="Dell"> <img src="https://cdn.worldvectorlogo.com/logos/dell-computer.svg" alt="Dell"> </div> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/hp-2.svg" alt="HP"> <img src="https://cdn.worldvectorlogo.com/logos/hp-2.svg" alt="HP"> </div> <div class="client-logo"> <img src="https://cdn.worldvectorlogo.com/logos/coca-cola-6.svg" alt="Coca Cola"> <img src="https://cdn.worldvectorlogo.com/logos/coca-cola-6.svg" alt="Coca Cola"> </div> </div>
自定义扩展说明
如果需要通过点击等非悬停事件触发动效,可以把CSS代码中的:hover替换为自定义类名(比如你之前写的.moveup),再通过JS控制类名的添加/移除即可。修正后的JS参考:
const logos = document.querySelectorAll('.client-logo') logos.forEach(logo => { logo.addEventListener('mouseenter', () => logo.classList.add('moveup')) logo.addEventListener('mouseleave', () => logo.classList.remove('moveup')) })
内容的提问来源于stack exchange,提问作者Shayan Kanwal
相关产品推荐
相关产品推荐

