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

React中集合容器展开动画实现方法咨询

实现集合数量变化时容器高度的平滑过渡动画

纯CSS方案(快速实现)

这种方案无需额外JS逻辑,利用CSS transition 和 max-height 属性实现过渡:

  • 给集合容器设置默认的max-height(对应显示少量项目时的高度),并添加过渡效果
  • 点击"Show more"时,给容器添加类名,将max-height设为足够容纳所有项目的数值(需根据实际内容调整)

示例代码:

.collection-container {
  max-height: 200px; /* 显示少量项目的高度 */
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.collection-container.expanded {
  max-height: 1000px; /* 足够容纳所有项目的高度 */
}
// React组件中切换类名
function Collection() {
  const [showMore, setShowMore] = useState(false);
  const items = Array.from({ length: showMore ? 10 : 3 }, (_, i) => `Item ${i+1}`);

  return (
    <div>
      <div className={`collection-container ${showMore ? 'expanded' : ''}`}>
        {items.map((item, idx) => (
          <div key={idx} style={{ padding: '10px', borderBottom: '1px solid #eee' }}>
            {item}
          </div>
        ))}
      </div>
      <button onClick={() => setShowMore(!showMore)}>
        {showMore ? 'Show less' : 'Show more'}
      </button>
    </div>
  );
}

React动态高度方案(精准过渡)

如果内容高度不确定,纯CSS的max-height可能导致过渡时长不准确,此时可以通过React的ref获取容器实际高度,动态触发过渡:

import { useState, useRef, useEffect } from 'react';

function Collection() {
  const [showMore, setShowMore] = useState(false);
  const containerRef = useRef(null);
  const [containerHeight, setContainerHeight] = useState('auto');

  const items = Array.from({ length: showMore ? 10 : 3 }, (_, i) => `Item ${i+1}`);

  useEffect(() => {
    if (!containerRef.current) return;
    
    // 先固定当前高度,再触发过渡到展开后的实际高度
    const currentHeight = containerRef.current.offsetHeight;
    setContainerHeight(`${currentHeight}px`);
    
    setTimeout(() => {
      const targetHeight = containerRef.current.scrollHeight;
      setContainerHeight(`${targetHeight}px`);
    }, 0);
  }, [showMore]);

  // 过渡完成后重置为auto,避免内容变化时高度受限
  useEffect(() => {
    if (!showMore || containerHeight === 'auto') return;
    const timer = setTimeout(() => setContainerHeight('auto'), 300); // 与transition时长一致
    return () => clearTimeout(timer);
  }, [showMore, containerHeight]);

  return (
    <div>
      <div
        ref={containerRef}
        style={{
          height: containerHeight,
          overflow: 'hidden',
          transition: 'height 0.3s ease',
        }}
      >
        {items.map((item, idx) => (
          <div key={idx} style={{ padding: '10px', borderBottom: '1px solid #eee' }}>
            {item}
          </div>
        ))}
      </div>
      <button onClick={() => setShowMore(!showMore)}>
        {showMore ? 'Show less' : 'Show more'}
      </button>
    </div>
  );
}

export default Collection;

动画库方案(简洁高效)

使用framer-motion这类动画库可以快速实现平滑过渡,无需手动处理高度计算:

import { useState } from 'react';
import { motion } from 'framer-motion';

function Collection() {
  const [showMore, setShowMore] = useState(false);
  const items = Array.from({ length: showMore ? 10 : 3 }, (_, i) => `Item ${i+1}`);

  return (
    <div>
      <motion.div
        style={{ overflow: 'hidden' }}
        animate={{ height: 'auto' }}
        transition={{ duration: 0.3 }}
      >
        {items.map((item, idx) => (
          <div key={idx} style={{ padding: '10px', borderBottom: '1px solid #eee' }}>
            {item}
          </div>
        ))}
      </motion.div>
      <button onClick={() => setShowMore(!showMore)}>
        {showMore ? 'Show less' : 'Show more'}
      </button>
    </div>
  );
}

export default Collection;

方案对比

  • 纯CSS:适合内容高度固定或可预估的简单场景,代码量最少
  • React动态高度:适合内容高度不确定的场景,过渡效果精准
  • 动画库:适合快速开发,无需关注底层高度计算,兼容性好

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:22:56