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

details元素关闭动画无法播放问题求助(附示例代码)

解决<details>元素收起动画不生效的问题

你的问题出在原生<details>的默认行为上:当用户点击summary关闭它时,浏览器会立刻移除open属性并隐藏内部内容,根本不给你的收起动画播放的机会。而且closed不是<details>的原生属性,你的details[closed]选择器完全不会被触发。

下面是修复方案:

核心思路

用JavaScript拦截默认的关闭行为,先播放收起动画,等动画结束后再真正关闭<details>;同时用自定义类来控制收起动画的触发,而不是依赖不存在的closed属性。

修改后的代码

CSS 部分

details {
  background: pink;
  overflow: hidden;
  /* 给默认状态设置基础高度,对应summary的高度 */
  height: 27px;
  transition: height 0.5s ease-in-out;
}

/* 展开状态:自动适应内容高度 */
details[open] {
  height: auto;
}

/* 收起动画的过渡类 */
details.closing {
  height: 27px;
}

summary {
  /* 确保summary可以被点击 */
  cursor: pointer;
  display: block;
}

这里把原来的关键帧动画改成了transition,更简洁,也更容易和JS配合。

HTML 部分

<details>
  <summary>Test</summary>
  This is a very cool test :)
  <br>woah
  <br>woah
</details>

JavaScript 部分

const details = document.querySelector('details');

details.addEventListener('toggle', (e) => {
  // 如果是关闭操作(open属性即将被移除)
  if (!details.open) {
    // 阻止默认关闭行为
    e.preventDefault();
    // 添加收起动画类
    details.classList.add('closing');
    
    // 监听动画结束事件
    const onTransitionEnd = () => {
      // 移除动画类
      details.classList.remove('closing');
      // 手动移除open属性,完成关闭
      details.removeAttribute('open');
      // 移除事件监听,避免重复触发
      details.removeEventListener('transitionend', onTransitionEnd);
    };
    
    details.addEventListener('transitionend', onTransitionEnd);
  }
});

为什么这样可行?

  • 拦截默认关闭行为后,我们可以先让元素通过transition平滑过渡到收起高度,等动画结束再真正关闭它。
  • 用transition代替关键帧动画,更适合这种从auto到固定高度的过渡(关键帧动画需要硬编码高度,不够灵活)。
  • 动画结束后清理事件监听和类,避免后续操作出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 22:32:12