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

CSS max-height过渡完成后内部HTML内容为何瞬间显示?

问题:max-height过渡动画时内部滚动容器内容延迟显示

我想实现一个点击按钮切换显示/隐藏的列表,通过父DIV的max-height过渡实现动画效果,同时让内部容器支持滚动。但目前父容器过渡流畅,内部HTML内容却要等过渡完成后才瞬间显示,且该问题仅在内部div内容溢出需要滚动时出现。我知道移除内部div、去掉其overflow属性或让它的高度与父容器一致能解决问题,但希望保留内部滚动功能,不清楚问题根源。

我的实现示例:

示例1

JavaScript

let visible = false;

function showHideList() {
  const listContainerRef = document.getElementById('list-id');
  if (!listContainerRef?.style?.maxHeight) 
    return;
    
  listContainerRef.style.maxHeight = visible ? 0 + 'px' : 200 + 'px';
  visible = !visible;
}

HTML

<button onclick="showHideList()" style="padding: 1rem; background: #2aabd2">Show / Hide</button>
<div id="list-id" style="transition: max-height 2s linear; overflow: hidden; max-height: 0;">
  <div style="overflow: auto; max-height: 200px">
    <div style="background-color: green">
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 1</span>
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 2</span>
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 3</span>
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 4</span>
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 5</span>
      <span style="display: block; background-color: red; padding: 0.5rem 0.75rem">Item 6</span>
    </div>
  </div>
</div>

示例2

CSS

#list-container {
    max-height: 0;
    transition: max-height 2s ease-out;
    overflow: hidden;
}
#list-container.visible {
    max-height: 300px;
}
#list-content {
    max-height: 200px;
    overflow: auto;
}
li {
    background-color: red;
    padding: 0.5rem 0.75rem;
}
button {
    padding: 1rem;
    background: #2aabd2;
}

HTML

<button onclick="document.getElementById('list-container').classList.toggle('visible')">Show / Hide</button>
  <div id="list-container">
      <div id="list-content">
    <ul>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
      </div>
</div>

问题原因

问题源于浏览器的布局优化机制:

  • 父容器通过max-height过渡时,实际高度动态变化。内部容器设置了overflow: auto,需要计算可用滚动空间,但浏览器为避免过渡过程中频繁重绘(每帧计算会消耗性能),会延迟计算内部容器的布局,直到父容器过渡完全结束。
  • 若内部容器的max-height与父容器过渡的目标max-height不一致,会加剧该问题:父容器拉伸过程中,内部容器高度未同步适配,导致内容一直被隐藏,直到父容器达到目标高度后,内部容器才突然获得足够空间显示内容。

解决方案

方案1:同步父容器与内部容器的高度

让内部容器高度完全适配父容器可用空间,过渡过程中内部容器能实时获取高度,浏览器同步计算滚动布局:
修改示例2的CSS:

#list-container {
    max-height: 0;
    transition: max-height 2s ease-out;
    overflow: hidden;
}
#list-container.visible {
    max-height: 200px; /* 和内部容器的max-height一致 */
}
#list-content {
    height: 100%; /* 改为height:100%,完全适配父容器高度 */
    max-height: 200px;
    overflow: auto;
}
/* 其他样式不变 */

方案2:提示浏览器提前准备布局变化

给父容器和内部容器添加will-change属性,告知浏览器元素高度会变化,提前做好布局计算准备,避免延迟:

#list-container {
    max-height: 0;
    transition: max-height 2s ease-out;
    overflow: hidden;
    will-change: max-height; /* 添加这行 */
}
#list-content {
    max-height: 200px;
    overflow: auto;
    will-change: height; /* 添加这行 */
}

方案3:用CSS变量统一高度值

用CSS变量定义目标高度,确保父容器和内部容器高度值完全一致,避免手动输入误差:

:root {
    --list-height: 200px;
}
#list-container {
    max-height: 0;
    transition: max-height 2s ease-out;
    overflow: hidden;
}
#list-container.visible {
    max-height: var(--list-height);
}
#list-content {
    height: 100%;
    max-height: var(--list-height);
    overflow: auto;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 17:15:54