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

Framer Motion:如何使外部div随AnimatePresence退出动画平滑过渡高度?

问题解决:Framer Motion 实现外层容器高度平滑过渡

你遇到的问题是列表元素退出时,外层fit-content高度的容器直接跳变,这是因为普通div无法感知子元素的动画过程,只能在元素完全移除后更新高度。用下面的方法可以解决:

核心方案:用 Framer Motion 的外层容器 + 布局动画

把外层的普通<div>换成<motion.div>,并添加layout属性,让它自动跟踪子元素的布局变化,生成平滑的高度过渡动画。同时优化子元素的退出动画配置,确保容器能正确捕捉尺寸变化。

修改后的代码示例

<motion.div 
  style={{ height: 'fit-content', backgroundColor: 'black' }}
  layout
  transition={{ layout: { type: 'spring', damping: 20, stiffness: 300 } }}
>
  <AnimatePresence mode={'wait'}>
    {items.map((id) => (
      <motion.div
        key={id}
        layout
        exit={{ opacity: 0, height: 0, margin: 0 }}
        transition={{ 
          opacity: { duration: 0.3 },
          layout: { type: 'spring' }
        }}
      >
        <Item key={id} />
      </motion.div>
    ))}
  </AnimatePresence>
</motion.div>

关键细节说明

  • 外层motion.div加layout:Framer Motion会自动计算子元素变化前后的容器尺寸,生成平滑的高度过渡动画,不需要手动写height的关键帧。
  • 子元素退出动画补充height:0和margin:0:让元素在淡出的同时逐步收缩自身尺寸,外层容器能实时感知到高度变化,避免跳变。
  • 修正key值:不要用-id这种可能导致重复的key,直接使用item的唯一标识,确保React能正确识别元素的添加/移除动作。
  • 拆分transition配置:可以给透明度动画和布局动画分别设置参数,让淡出和高度变化的节奏更协调。

如果不想用Framer Motion,也可以用CSS的max-height过渡,但需要预估列表项的最大高度,灵活性不如Framer Motion的方案:

.container {
  transition: max-height 0.5s ease;
  max-height: 1000px; /* 设为足够大的值 */
  overflow: hidden;
}
.container.shrinking {
  max-height: 0;
}

但这种方法需要手动控制类名切换,不如Framer Motion的自动布局动画方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:10:17