React组件中CSS Transition动画不生效,需实现内容展开推挤下方元素
问题:CSS Transition高度过渡动画不生效,高度瞬间切换
我用React实现了一个展开/收起组件:通过按钮切换div的height样式属性(0和100%),已经给该div配置了CSS Transition属性,但实际效果是高度瞬间切换,过渡时长只起到了延迟作用,没有预期的平滑动画。
试过用position: fixed能实现动画,但会导致内容覆盖下方元素,我需要展开时能推挤下面的内容。
组件代码
const Component = () => { const [isOpen, setOpen] = useState(false); return ( <div> <button onClick={() => setOpen(!isOpen)}>Show Content</button> <div className="content" style={{ height: isOpen ? "100%" : 0 }}> <p>Content</p> </div> </div> ); };
CSS代码
.content { height: 0; overflow: hidden; transition: height ease 0.5s; border-style: solid; }
解决方法
原因
CSS Transition无法在0和100%这类百分比高度值之间计算过渡动画——因为浏览器无法确定100%对应的具体像素高度(除非父元素有固定高度),所以只能直接跳变。
方案1:使用内容实际像素高度切换
通过Ref获取内容的实际高度,用具体像素值代替百分比来触发过渡:
import { useState, useRef, useEffect } from 'react'; const Component = () => { const [isOpen, setOpen] = useState(false); const contentRef = useRef(null); const [contentHeight, setContentHeight] = useState(0); useEffect(() => { if (isOpen) { // 展开时获取内容实际高度 setContentHeight(`${contentRef.current.scrollHeight}px`); } else { // 收起时先设置为实际高度,再延迟设为0触发过渡 setContentHeight(`${contentRef.current.scrollHeight}px`); const timer = setTimeout(() => { setContentHeight(0); }, 10); return () => clearTimeout(timer); } }, [isOpen]); return ( <div> <button onClick={() => setOpen(!isOpen)}>Show Content</button> <div ref={contentRef} className="content" style={{ height: contentHeight }} > <p>Content</p> <p>可以添加更多内容测试效果</p> </div> </div> ); };
CSS保持原代码不变即可。
方案2:用max-height替代height
设置一个足够大的max-height值,通过切换max-height实现过渡(更简单但需注意max-height的取值):
.content { max-height: 0; overflow: hidden; transition: max-height ease 0.5s; border-style: solid; } .content.open { max-height: 500px; /* 设一个比内容最大高度大的数值 */ }
const Component = () => { const [isOpen, setOpen] = useState(false); return ( <div> <button onClick={() => setOpen(!isOpen)}>Show Content</button> <div className={`content ${isOpen ? 'open' : ''}`}> <p>Content</p> </div> </div> ); };
注意:max-height的值不要设得过大,否则动画前半段会显得很快(因为大部分高度是空白),尽量贴近内容的实际最大高度。
内容的提问来源于stack exchange,提问作者antshekhter
相关产品推荐
相关产品推荐

