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

如何在添加动态内容时实现div高度平滑展开,无需设置固定高度

核心实现原理

CSS 原生 transition 不支持对 height: auto 做属性插值过渡,因此直接给容器加高度过渡不会生效。以下是两种适配动态内容高度的实现方案,无需固定高度即可实现平滑展开:


方案1:纯CSS Grid实现(推荐,无JS逻辑,适配所有动态高度)

无需计算内容高度,仅靠CSS即可实现任意高度内容的平滑过渡,现代浏览器兼容性优秀。

React 代码修改
const [isOpen, setIsOpen] = useState(false)

const toggle = () => {
    setIsOpen(!isOpen)
}

return (
  <div className="container">
    <h1>TEST CONTAINER</h1>
    {/* 新增内容包裹层,不需要删除原有的条件渲染逻辑,也可以保留组件挂载状态 */}
    <div className={`content-wrapper ${isOpen ? 'open' : ''}`}>
      <Paragraph />
    </div>
    <button type="button" class="btn btn-primary" onClick={toggle}>Primary</button>
  </div>
);
}
CSS 代码修改
.container {
  margin-left: 30%;
  margin-top: 10%;
  width: 500px;
  height: auto;
  background-color: whitesmoke;
}

/* 内容包裹层样式 */
.content-wrapper {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
  overflow: hidden;
}
.content-wrapper.open {
  grid-template-rows: 1fr;
}

/* 可选:添加内容淡入效果,让过渡更自然 */
.content-wrapper > * {
  min-height: 0;
  opacity: 0;
  transition: opacity 0.2s ease 0.1s;
}
.content-wrapper.open > * {
  opacity: 1;
}

方案2:JS动态计算高度(兼容性更好,适配低版本浏览器)

如果需要兼容不支持Grid过渡的低版本浏览器,可以用JS动态获取内容高度实现过渡,展开后自动切回height: auto不影响后续内容动态更新。

React 代码修改
import { useRef, useState, useEffect } from 'react';

const [isOpen, setIsOpen] = useState(false);
const contentWrapperRef = useRef(null);
const innerContentRef = useRef(null);

const toggle = () => {
  setIsOpen(!isOpen);
};

useEffect(() => {
  if (isOpen) {
    // 展开时读取内容实际高度触发过渡
    const contentHeight = innerContentRef.current.scrollHeight;
    contentWrapperRef.current.style.height = `${contentHeight}px`;
    // 过渡结束后切回auto,适配后续内容高度变化
    const onTransitionEnd = () => {
      contentWrapperRef.current.style.height = 'auto';
      contentWrapperRef.current.removeEventListener('transitionend', onTransitionEnd);
    };
    contentWrapperRef.current.addEventListener('transitionend', onTransitionEnd);
  } else {
    // 收起时先固定为当前高度再切为0触发过渡
    contentWrapperRef.current.style.height = `${contentWrapperRef.current.scrollHeight}px`;
    // 强制浏览器重绘确保高度变更生效
    void contentWrapperRef.current.offsetHeight;
    contentWrapperRef.current.style.height = '0px';
  }
}, [isOpen]);

return (
  <div className="container">
    <h1>TEST CONTAINER</h1>
    <div ref={contentWrapperRef} className="dynamic-content-wrapper">
      <div ref={innerContentRef}>
        <Paragraph />
      </div>
    </div>
    <button type="button" class="btn btn-primary" onClick={toggle}>Primary</button>
  </div>
);
}
CSS 代码修改
.container {
  margin-left: 30%;
  margin-top: 10%;
  width: 500px;
  height: auto;
  background-color: whitesmoke;
}

.dynamic-content-wrapper {
  height: 0;
  overflow: hidden;
  transition: height 0.3s ease;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 05:27:02