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

如何实现<details>鼠标悬停展开、移出折叠(含内部内容)

问题

HTML的<details>元素默认是点击展开/折叠,现在需要修改为:

  • 鼠标移入时展开
  • 鼠标移出时折叠,但只有当鼠标完全离开<details>及其内部的<summary>元素时才执行折叠

原代码示例:

window.addEventListener("load", () => {
  const details = document.body.querySelectorAll("details");
  for (const detail of details) {
    detail.addEventListener("mouseover", (evt) => {
      console.log(evt.target.parentElement.setAttribute("open", true));
    });
    detail.addEventListener("mouseout", (evt) => {
      console.log(evt.target.parentElement.removeAttribute("open"));
    });
  }
});
<details>
  <summary>summary</summary>
  internal details
</details>
解决方案

原代码的问题在于用了mouseover/mouseout事件,这两个事件会在鼠标在子元素间移动时频繁触发,导致不必要的展开/折叠。改用mouseenter/mouseleave事件就能解决——它们不会冒泡,且mouseleave仅在鼠标完全离开整个元素(包括所有子元素)时才触发。同时要禁用<summary>的默认点击行为,避免和hover逻辑冲突。

修正后的代码如下:

HTML(无需修改)

<details>
  <summary>summary</summary>
  internal details
</details>

JavaScript

window.addEventListener("load", () => {
  const details = document.body.querySelectorAll("details");
  details.forEach(detail => {
    // 鼠标移入时展开
    detail.addEventListener("mouseenter", () => {
      detail.setAttribute("open", true);
    });

    // 鼠标完全离开时折叠
    detail.addEventListener("mouseleave", () => {
      detail.removeAttribute("open");
    });

    // 禁用summary的默认点击行为,避免点击干扰hover逻辑
    const summary = detail.querySelector("summary");
    summary.addEventListener("click", (e) => {
      e.preventDefault();
    });
  });
});

逻辑说明

  • mouseenter:当鼠标第一次进入<details>元素(包括子元素)时触发,设置open属性展开内容。
  • mouseleave:只有当鼠标完全离开<details>及其所有子元素时才触发,移除open属性实现折叠。
  • 禁用<summary>点击默认行为:防止用户点击summary时触发原生的展开/折叠逻辑,保证只有hover控制状态。

内容的提问来源于stack exchange,提问作者Mr.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:34:58