基于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
相关产品推荐
相关产品推荐

