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

Div自动高度切换动画问题排查与解决

Hey there! Let's break down your issues one by one and fix them up.

Why the open animation isn't working

The main problem here is that you're missing overflow: hidden in your styled component. Here's why that matters:

  • When the div is closed (max-height: 20px), without overflow: hidden, the content inside still spills out (since default overflow is visible). That means the actual height of the div is already the full height of your content, not 20px.
  • When you switch to open: true, the max-height jumps from 20px to 500px, but since the div's height is already at the content's full height, there's nothing to animate—you don't see any transition because the height doesn't change.

Quick fix for the open animation

Just add overflow: hidden to your Container styles:

const Container = styled.div`
  margin: 5px;
  padding: 10px;
  width: 200px;
  max-height: ${props => (props.open ? '500px' : '20px')};
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: max-height 1s cubic-bezier(0, 1, 0.5, 1);
  background-color: #f6f6f6;
  cursor: pointer;
  overflow: hidden; // Add this line!
`;

Now when closed, the content is clipped, and when opening, the div's height will gradually expand from 20px up to the content's actual height (stopping once it hits that, even if max-height is set to 500px). The animation will work as expected.

Fixing the fixed animation duration issue

Setting a hard max-height: 500px means even if your content is only 100px tall, the transition still takes the full 1s—this feels slow and unnatural. To fix this, we need to dynamically calculate the actual height of the content and adjust both max-height and the transition duration based on that.

Solution: Use JavaScript to get the content's real height

Here's how to implement this with React hooks:

  1. Use a ref to access the content inside the collapsible div.
  2. Calculate the content's scrollHeight (the full height of the content, even if clipped).
  3. Pass this height as a prop to your styled component, and use it to set max-height when open.
  4. Adjust the transition duration proportionally to the content height (so shorter content animates faster).

Here's the full code example:

import { useState, useRef, useEffect } from 'react';
import styled from 'styled-components';

const Container = styled.div`
  margin: 5px;
  padding: 10px;
  width: 200px;
  max-height: ${props => (props.open ? `${props.contentHeight}px` : '20px')};
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2);
  transition: max-height ${props => `${props.animationDuration}s`} cubic-bezier(0, 1, 0.5, 1);
  background-color: #f6f6f6;
  cursor: pointer;
  overflow: hidden;
`;

const CollapsibleSection = () => {
  const [open, setOpen] = useState(false);
  const contentRef = useRef(null);
  const [contentHeight, setContentHeight] = useState(0);
  const [animationDuration, setAnimationDuration] = useState(1);

  // Calculate content height on component mount
  useEffect(() => {
    if (contentRef.current) {
      const fullHeight = contentRef.current.scrollHeight;
      setContentHeight(fullHeight);
      // Adjust duration: e.g., 1s for 500px tall content, scale down for shorter content
      setAnimationDuration(Math.min(fullHeight / 500, 1));
      // Cap duration at 1s so it doesn't get too slow for very long content
    }
  }, []);

  return (
    <Container
      open={open}
      onClick={() => setOpen(!open)}
      contentHeight={contentHeight}
      animationDuration={animationDuration}
    >
      {/* Wrap your content in a div with the ref */}
      <div ref={contentRef}>
        Your dynamic content goes here—whether it's short text or a long paragraph, the animation will adapt!
      </div>
    </Container>
  );
};

export default CollapsibleSection;

How this works:

  • When the component mounts, we grab the full height of the content using scrollHeight.
  • We set max-height to that exact height when open, so the div only expands as much as needed.
  • The animation duration is scaled based on the content height (e.g., a 250px tall content will animate in 0.5s, while a 500px+ content uses the full 1s).

This gives you a smooth, natural-feeling animation that adapts to whatever content you put inside.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:47:57