手风琴组件展开时CSS transition生效,收起时无过渡效果求助
React手风琴组件收起时过渡动画失效的解决方案
问题原因
你当前的实现中,手风琴内容区域(.body)是通过{isOpen && ...}进行条件渲染的:当收起(isOpen=false)时,元素会被直接从DOM中移除,导致CSS transition没有执行时间,因此看不到收起动画;而展开时元素存在,maxHeight从0过渡到内容高度,动画正常生效。
修复方案
核心思路是始终保留内容区域的DOM节点,通过控制maxHeight属性实现展开/收起动画,而非卸载元素。
修改后的React代码
import React, { useEffect, useRef, useState } from "react"; import cx from "classnames"; import styles from "./accordion.module.scss"; export const Accordion = ({ bodyText, headerText }) => { const accordionRef = useRef(null); const [isOpen, setIsOpen] = useState(false); const [height, setHeight] = useState("0px"); useEffect(() => { handleSetHeight(); }, [isOpen]); function handleSetHeight() { if (accordionRef.current) { setHeight(isOpen ? `${accordionRef.current.scrollHeight}px` : "0px"); } } return ( <div className={cx(styles.accordion, { [styles["accordion--active"]]: isOpen, })} > <div className={styles.item}> <div className={styles.header} onClick={() => setIsOpen((prev) => !prev)} > <div>{headerText}</div> <div>{isOpen ? "-" : "+"}</div> </div> {/* 移除条件渲染,始终保留内容区域节点 */} <div className={styles.body} ref={accordionRef} style={{ maxHeight: height }} > <p>{bodyText}</p> </div> </div> </div> ); };
优化后的CSS代码(可选)
可以将过渡属性从all改为max-height,减少不必要的过渡计算,提升性能:
@import "../../colors.scss"; .accordion { width: 100%; display: flex; flex-direction: column; box-sizing: border-box; margin-bottom: 1rem; border: 2px solid #afafaf; transition: all 350ms ease-in-out; &--active { border: 2px solid $black; box-shadow: 0rem 0.25rem 0.5rem #515151; transition: all 350ms ease-in-out; } &:last-of-type { margin-bottom: 0rem; } .item { .body { overflow: hidden; /* 明确仅过渡max-height属性 */ transition: max-height 350ms ease-in-out; background-color: $white; padding: 0rem 1rem; box-sizing: border-box; max-height: 0px; p { margin-bottom: 1rem; margin-top: 0rem; } } .header { display: flex; justify-content: space-between; background-color: $white; font-size: 2.5rem; padding: 1rem; cursor: pointer; } } }
修复说明
- 移除条件渲染后,内容区域始终存在于DOM中,收起时
maxHeight从内容高度过渡到0,动画可以正常执行。 - 确保
accordionRef始终能获取到元素节点,handleSetHeight可以正确计算并设置高度值。 - 可选的图标切换(
+/-)提升用户交互体验。
内容的提问来源于stack exchange,提问作者user11631308
相关产品推荐
相关产品推荐

