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

基于height属性的折叠动画添加内容后无法显示的问题求助

问题:动态更新折叠区域内容后,新内容无法显示(需保留动画效果)

我通过height属性实现了折叠区域的平滑显示/隐藏动画,但向折叠区域添加新内容后,新内容会超出预先设定的height值而被隐藏,必须先点击按钮隐藏区域再重新打开,才能看到新增内容。试过将height设为null,但动画效果会消失,想知道如何在保留动画的前提下,让新增内容正常显示。

最小复现示例(MRE)

JavaScript 代码

function changeVisility(all, toCancel = null) {
    if(toCancel != null)
        toCancel.preventDefault();
    if(!(Symbol.iterator in Object(all)))
        all = [ all ];
    for(var div of all) {
        for(const wrapper of div.querySelectorAll(".collapse-wrapper")) {
            if(wrapper.style.height == '0px') {
                wrapper.style.height = wrapper.querySelector(".collapse-content").getBoundingClientRect().height + `px`;
            } else {
                wrapper.style.height = '0px';
            }
        }
    }
}

for(const wrapper of document.querySelectorAll(".collapse-wrapper")) {
    if(wrapper.style.height != '0px') { // set real height
        wrapper.style.height = wrapper.querySelector(".collapse-content").getBoundingClientRect().height + `px`;
    } else
        wrapper.style.height = '0px';
}

function addContent() {
    document.getElementById("contentToAdd").insertAdjacentHTML("beforeend", "<p>Other text</p>");
}

CSS 代码

.collapse-wrapper {
    overflow: hidden;
    transition: height 300ms ease-in;
}

HTML 代码

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">

<body style="margin-left: 10px;">
<div class="form-check" style="padding-top: 0.5rem;">
    <input class="form-check-input" type="checkbox" name="newinput" id="newinput" onchange="changeVisility(document.getElementById('input_selection'));">
    <label class="form-check-label" for="newinput">
        Open
    </label>
</div>
<div id="input_selection">
    <div style="height: 0px;" class="collapse-wrapper">
        <div class="collapse-content row" id="contentToAdd" style="background-color: red;">
            <button onclick="addContent()" type="button" class="btn btn-primary">Add</button>
            <p>Some text</p>
        </div>
    </div>
</div>
</body>

复现步骤

  • 点击“Open”按钮打开折叠区域
  • 点击“Add”按钮——内容已添加到HTML中,但视觉上无变化
  • 连续点击两次“Open”按钮(先隐藏再重新打开)
  • 红色区域高度更新,新增的“Other text”内容可见

解决方案

核心问题:折叠区域处于打开状态时,collapse-wrapper的height是固定值,新增内容后容器实际高度变化,但这个固定值没有更新,导致内容被截断。

修改方案(保留动画的同时动态更新高度)

提取统一的高度设置函数,并在新增内容后主动更新打开状态下的容器高度:

// 统一处理折叠容器高度的工具函数
function setCollapseHeight(wrapper, isOpen) {
  const content = wrapper.querySelector(".collapse-content");
  wrapper.style.height = isOpen ? `${content.getBoundingClientRect().height}px` : '0px';
}

function changeVisility(all, toCancel = null) {
  if(toCancel != null)
      toCancel.preventDefault();
  if(!(Symbol.iterator in Object(all)))
      all = [ all ];
  for(var div of all) {
    for(const wrapper of div.querySelectorAll(".collapse-wrapper")) {
      const isOpen = wrapper.style.height === '0px';
      setCollapseHeight(wrapper, isOpen);
    }
  }
}

// 初始化折叠容器高度
for(const wrapper of document.querySelectorAll(".collapse-wrapper")) {
  const isOpen = wrapper.style.height !== '0px';
  setCollapseHeight(wrapper, isOpen);
}

function addContent() {
  const contentContainer = document.getElementById("contentToAdd");
  contentContainer.insertAdjacentHTML("beforeend", "<p>Other text</p>");
  
  // 找到对应的折叠容器
  const wrapper = contentContainer.closest(".collapse-wrapper");
  // 如果容器处于打开状态,立即更新高度
  if (wrapper.style.height !== '0px') {
    setCollapseHeight(wrapper, true);
  }
}

说明

  • 提取setCollapseHeight函数,避免重复代码,统一处理高度计算逻辑
  • 在addContent函数中,新增内容后判断折叠容器是否处于打开状态,若是则重新计算并设置容器高度,浏览器会自动触发transition动画,实现平滑的高度更新
  • CSS和HTML部分无需修改,保持原有动画逻辑

备选方案(使用max-height,无需计算高度)

如果不想动态计算高度,可以改用max-height实现动画,但需要设置一个足够大的max-height值来覆盖内容可能的最大高度:

.collapse-wrapper {
  overflow: hidden;
  transition: max-height 300ms ease-in;
  max-height: 0;
}
.collapse-wrapper.open {
  max-height: 2000px; /* 根据实际内容调整这个值 */
}

对应的JS修改为切换open类:

function changeVisility(all, toCancel = null) {
  if(toCancel != null)
      toCancel.preventDefault();
  if(!(Symbol.iterator in Object(all)))
      all = [ all ];
  for(var div of all) {
    for(const wrapper of div.querySelectorAll(".collapse-wrapper")) {
      wrapper.classList.toggle("open");
    }
  }
}

function addContent() {
  const contentContainer = document.getElementById("contentToAdd");
  contentContainer.insertAdjacentHTML("beforeend", "<p>Other text</p>");
}

这种方案无需计算高度,但如果内容高度超过设定的max-height,依然会出现内容截断的问题,适合内容高度可控的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 21:50:19