You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为鼠标悬停/移出事件的样式变化添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 00:40:59