如何为鼠标悬停/移出事件的样式变化添加CSS过渡效果
问题描述
我修改了锚点标签和图标的样式,想给这些样式变化添加过渡效果,但不知道怎么实现。
鼠标悬停列表项时显示“VISIT”链接并隐藏图标,鼠标移出时隐藏链接并显示图标。我以为给锚点标签加transition:1s就能让所有样式变化产生过渡,但没达到预期效果。
相关代码
JavaScript
const listItems = document.querySelectorAll("nav ul li"); const icons = document.querySelectorAll("nav ul li i"); const visitButtons = document.querySelectorAll("nav ul li a.visit--link"); listItems.forEach((item, id) => { item.addEventListener("mouseover", function() { icons[id].style.display = "none"; visitButtons[id].style.transform = "translateX(0%)"; visitButtons[id].style.display = "inline-block"; }); item.addEventListener("mouseout", function() { icons[id].style.display = "inline-block"; visitButtons[id].style.transform = "translateX(100%)"; visitButtons[id].style.display = "none"; }); });
CSS
nav { width: 30%; border: 1px solid #333; border-radius: 5px; display: flex; flex-direction: column; } h2 { font-size: 36px; text-align: center; border-bottom: 1px solid #333; justify-content: center; margin: 0; padding: 15px 30px; } nav ul { padding: 0; margin: 0; } nav ul li { list-style-type: none; position: relative; display: flex; justify-content: space-between; align-items: center; transition: 2s; } nav ul li i { margin: 0px 5px; } nav ul li a { text-decoration: none; margin: 0; color: #000; } nav ul li i, nav ul li a { font-size: 36px; padding: 15px; } nav ul li a.visit--link { background-color: #80d6ff; color: #fff; transform: translateX(100%); display: none; }
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Sliding Sidebar</title> <script src="https://kit.fontawesome.com/02de928ecb.js" crossorigin="anonymous"></script> </head> <body> <nav> <h2>MOST POPULAR CASINOS</h2> <ul> <li> <div> <a href="#"><i class="fa-brands fa-fantasy-flight-games"></i>MUCHO VEGAS</a > </div> <a href="#" class="visit--link">VISIT</a> </li> <li> <div> <a href="#"><i class="fa-brands fa-fantasy-flight-games"></i>LOKI</a > </div> <a href="#" class="visit--link">VISIT</a> </li> <li> <div> <a href="#"><i class="fa-brands fa-fantasy-flight-games"></i>GOLDEN STAR</a > </div> <a href="#" class="visit--link">VISIT</a> </li> <li> <div> <a href="#"><i class="fa-brands fa-fantasy-flight-games"></i>BITSTARY</a > </div> <a href="#" class="visit--link">VISIT</a> </li> <li> <div> <a href="#"><i class="fa-brands fa-fantasy-flight-games"></i>GUNSBET</a > </div> <a href="#" class="visit--link">VISIT</a> </li> </ul> </nav> </body> </html>
解决方案
问题根源
display属性无法产生过渡动画,它的切换是瞬间完成的;同时设置display:none会让元素脱离文档流,导致transform的过渡效果直接失效。要实现平滑过渡,需要改用opacity或visibility控制显示隐藏,同时保留元素在文档流中的位置。
推荐方案:用CSS hover实现(简洁高效)
完全无需JS,通过CSS伪类就能实现所有交互,代码更简洁且性能更好:
修改后的CSS
nav { width: 30%; border: 1px solid #333; border-radius: 5px; display: flex; flex-direction: column; } h2 { font-size: 36px; text-align: center; border-bottom: 1px solid #333; justify-content: center; margin: 0; padding: 15px 30px; } nav ul { padding: 0; margin: 0; } nav ul li { list-style-type: none; position: relative; display: flex; justify-content: space-between; align-items: center; overflow: hidden; /* 隐藏超出li范围的元素 */ } nav ul li i { margin: 0px 5px; transition: opacity 0.3s ease; /* 图标透明度过渡 */ } nav ul li a { text-decoration: none; margin: 0; color: #000; } nav ul li i, nav ul li a { font-size: 36px; padding: 15px; } nav ul li a.visit--link { background-color: #80d6ff; color: #fff; transform: translateX(100%); /* 初始移出视野 */ opacity: 0; /* 初始透明 */ pointer-events: none; /* 初始不可点击 */ transition: all 0.3s ease; /* 过渡所有变化属性 */ position: absolute; right: 0; /* 固定右侧位置 */ } /* 鼠标悬停li时的状态切换 */ nav ul li:hover i { opacity: 0; } nav ul li:hover a.visit--link { transform: translateX(0%); opacity: 1; pointer-events: auto; /* 恢复可点击 */ }
注意事项
- 移除原有的JS代码,CSS已完全实现交互逻辑
- 给
li添加overflow:hidden,避免VISIT链接移出时显示在li外部
备选方案:用JS实现的修改版
如果一定要保留JS控制,需把display切换改为opacity+pointer-events,同时保留元素位置:
修改后的JS
const listItems = document.querySelectorAll("nav ul li"); const icons = document.querySelectorAll("nav ul li i"); const visitButtons = document.querySelectorAll("nav ul li a.visit--link"); listItems.forEach((item, id) => { item.addEventListener("mouseover", function() { icons[id].style.opacity = "0"; visitButtons[id].style.transform = "translateX(0%)"; visitButtons[id].style.opacity = "1"; visitButtons[id].style.pointerEvents = "auto"; }); item.addEventListener("mouseout", function() { icons[id].style.opacity = "1"; visitButtons[id].style.transform = "translateX(100%)"; visitButtons[id].style.opacity = "0"; visitButtons[id].style.pointerEvents = "none"; }); });
修改后的CSS(对应JS方案)
/* 其他样式不变,仅修改以下部分 */ nav ul li { list-style-type: none; position: relative; display: flex; justify-content: space-between; align-items: center; overflow: hidden; } nav ul li i { margin: 0px 5px; transition: opacity 0.3s ease; } nav ul li a.visit--link { background-color: #80d6ff; color: #fff; transform: translateX(100%); opacity: 0; pointer-events: none; transition: all 0.3s ease; position: absolute; right: 0; }
核心要点
- 避免用
display:none/block控制过渡,改用opacity(控制透明度)+pointer-events(控制交互性) - 给需要过渡的属性(如
opacity、transform)添加transition声明 - CSS hover方案比JS更轻量化,减少DOM操作,性能更优
内容的提问来源于stack exchange,提问作者marigold
相关产品推荐
相关产品推荐

