React项目中CSS宽度切换时如何实现子元素淡入淡出动画?
实现切换视图时子元素淡入淡出的方案
一、纯CSS实现
完全可以用CSS实现该效果,通过结合过渡(transition)或关键帧动画(@keyframes),配合wrapper的类切换来触发子元素的淡入淡出。
方案1:过渡延迟配合宽度动画
让子元素的淡入淡出和宽度变化同步,实现流畅衔接:
.wrapper { transition: width 500ms ease-in-out; /* 其他基础样式,如margin、padding等 */ } .wrapper.desktop { width: 720px; } .wrapper.mobile { width: 320px; } /* 子元素基础样式 */ .wrapper > * { opacity: 1; /* 延迟250ms后开始淡入,和宽度变化的后半段同步 */ transition: opacity 250ms ease-in-out 250ms; } /* 切换类时,子元素立即淡出 */ .wrapper.desktop > *, .wrapper.mobile > * { opacity: 0; transition-delay: 0ms; }
效果说明:点击切换后,子元素先在250ms内淡出,同时wrapper开始宽度变化;当宽度变化到一半时,子元素开始淡入,刚好在宽度变化完成时淡入结束。
方案2:关键帧动画
如果需要更精细的动画节奏(比如中间保持透明一段时间),可以用关键帧动画:
.wrapper { transition: width 500ms ease-in-out; } .wrapper.desktop { width: 720px; } .wrapper.mobile { width: 320px; } /* 定义淡入淡出关键帧 */ @keyframes fadeInOut { 0% { opacity: 1; } 30% { opacity: 0; } /* 淡出到透明 */ 70% { opacity: 0; } /* 保持透明 */ 100% { opacity: 1; } /* 淡入 */ } /* 切换类时触发动画 */ .wrapper.desktop > *, .wrapper.mobile > * { animation: fadeInOut 500ms ease-in-out forwards; }
效果说明:子元素会跟随宽度变化的节奏,先淡出、短暂保持透明,再淡入,避免内容在宽度变化过程中出现排版错乱。
二、React实现方案
如果需要更灵活的控制(比如结合数据加载、复杂状态逻辑),可以用React的状态管理或专门的过渡库实现:
方案1:原生状态控制
通过React状态控制子元素的透明度,配合定时器实现动画衔接:
import { useState } from 'react'; const ViewToggle = () => { const [isDesktop, setIsDesktop] = useState(true); const [contentVisible, setContentVisible] = useState(true); const toggleView = () => { // 先让内容淡出 setContentVisible(false); // 等待淡出完成后切换宽度类,再触发淡入 setTimeout(() => { setIsDesktop(!isDesktop); setContentVisible(true); }, 250); }; return ( <div className={`wrapper ${isDesktop ? 'desktop' : 'mobile'}`}> <div className="content" style={{ opacity: contentVisible ? 1 : 0, transition: 'opacity 250ms ease-in-out' }} > {/* 你的页面内容 */} <h1>示例内容</h1> <p>这是要切换视图的内容</p> </div> <button onClick={toggleView}> 切换到{isDesktop ? '移动端' : '桌面端'}视图 </button> </div> ); }; export default ViewToggle;
方案2:使用React Transition Group库
对于更复杂的过渡场景,推荐使用react-transition-group库,它提供了开箱即用的过渡组件:
- 安装依赖:
npm install react-transition-group
- 实现代码:
import { useState } from 'react'; import { CSSTransition } from 'react-transition-group'; const ViewToggle = () => { const [isDesktop, setIsDesktop] = useState(true); // 通过key值触发组件重新渲染,触发过渡动画 const [contentKey, setContentKey] = useState('desktop'); const toggleView = () => { setIsDesktop(!isDesktop); setContentKey(isDesktop ? 'mobile' : 'desktop'); }; return ( <div className={`wrapper ${isDesktop ? 'desktop' : 'mobile'}`}> <CSSTransition key={contentKey} timeout={500} classNames="content-transition" unmountOnExit > <div className="content"> <h1>{isDesktop ? '桌面端内容' : '移动端内容'}</h1> <p>适配对应视图的排版</p> </div> </CSSTransition> <button onClick={toggleView}> 切换到{isDesktop ? '移动端' : '桌面端'}视图 </button> </div> ); }; export default ViewToggle;
- 对应CSS样式:
.content-transition-enter { opacity: 0; } .content-transition-enter-active { opacity: 1; transition: opacity 250ms ease-in-out 250ms; } .content-transition-exit { opacity: 1; } .content-transition-exit-active { opacity: 0; transition: opacity 250ms ease-in-out; }
内容的提问来源于stack exchange,提问作者Hossein Ahmadi
相关产品推荐
相关产品推荐

