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

如何实现从百分比max-height到固定像素height的过渡动画?

实现从百分比max-height到固定像素height的过渡动画

核心问题在于:元素展开状态下height默认是auto,而CSS过渡需要明确的数值起点和终点才能生效。我们可以通过以下方式解决:

  1. 展开状态时,动态获取元素的实际高度(受max-height:60%限制),将其设为元素的height值
  2. 最小化时,将height设为固定的55px,利用CSS过渡实现平滑动画
  3. 监听窗口resize事件,在窗口尺寸变化时更新展开状态下的元素高度,适配不同屏幕

修改后的代码示例

React 代码

const { useState, useRef, useEffect } = React;

const App = () => {
  const [isMinimized, setIsMinimized] = useState(false);
  const containerRef = useRef(null);

  // 处理展开/最小化时的高度设置
  useEffect(() => {
    const container = containerRef.current;
    if (!container) return;

    if (!isMinimized) {
      // 展开时,先重置height为auto,获取实际高度后再设置为固定值
      container.style.height = 'auto';
      const computedHeight = container.offsetHeight;
      container.style.height = `${computedHeight}px`;
    } else {
      // 最小化时设置固定高度
      container.style.height = '55px';
    }
  }, [isMinimized]);

  // 监听窗口resize,更新展开状态下的高度
  useEffect(() => {
    const handleResize = () => {
      const container = containerRef.current;
      if (!container || isMinimized) return;
      
      container.style.height = 'auto';
      const computedHeight = container.offsetHeight;
      container.style.height = `${computedHeight}px`;
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, [isMinimized]);

  return (
    <div className="App">
      <div 
        ref={containerRef}
        className={`container ${isMinimized ? 'container-minimized' : ''}`}
      >
        <p>Foo</p>
        <p>Bar</p>
        <p>Foobar</p>
        <div
          onClick={() => setIsMinimized(!isMinimized)}
          className="minimize-element"
        >
          <span />
        </div>
      </div>
    </div>
  );
}

ReactDOM.render(
    <App />,
    document.getElementById("root")
);

CSS 代码

.App {
  font-family: sans-serif;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.container {
  transition: height 0.3s ease-out;
  width: 100%;
  background-color: hotpink;
  top: 0;
  left: 0;
  position: fixed;
  box-shadow: 0px 3px 3px -2px rgba(0, 0, 0, 0.2),
    0px 3px 4px 0px rgba(0, 0, 0, 0.14), 0px 1px 8px 0px rgba(0, 0, 0, 0.12);
  max-height: 60%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.minimize-element {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin-top: auto;
  background-color: yellowgreen;
  padding-top: 4px;
  padding-bottom: 4px;
}

.minimize-element:hover {
  cursor: pointer;
}

.minimize-element > span {
  background-color: red;
  width: 35px;
  height: 6px;
  border-radius: 7px;
}

HTML 代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.development.js"></script>
<div id="root"></div>

关键说明

  • 通过useRef获取容器元素,动态计算并设置展开状态下的实际高度,确保过渡有明确的数值起点
  • 监听窗口resize事件,在屏幕尺寸变化时重新计算高度,保证适配性
  • 调整了minimize-element的margin-top为auto,让按钮始终固定在容器底部,布局更合理

内容的提问来源于stack exchange,提问作者four-eyes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 11:38:22