如何实现<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.
相关产品推荐
相关产品推荐

