如何让React实现的Toggle Switch切换开关具备响应式特性?
响应式React Toggle Switch实现方案
核心优化思路
- 移除容器固定宽高,让组件根据内部文本自动适配宽度,用padding控制高度
- 简化组件结构,避免重复渲染相同内容,通过单个遮罩层实现切换效果
- 用CSS类管理切换状态,替代内联样式的
clipPath,提升可维护性 - 添加移动端响应式适配,调整字体和间距保证小屏幕体验
修改后的React组件代码
import { useState } from "react"; import styles from "./ToggleSwitch.module.css"; export default function ToggleSwitch({ choice1, choice2 }) { const [isChoice1Active, setIsChoice1Active] = useState(false); const handleClick = () => { setIsChoice1Active(prev => !prev); }; return ( <div className={styles.container} onClick={handleClick}> {/* 底层文本容器 */} <div className={styles.labelsContainer}> <span className={styles.label}>{choice2}</span> <span className={styles.label}>{choice1}</span> </div> {/* 激活状态遮罩 */} <div className={`${styles.activeMask} ${isChoice1Active ? styles.shiftLeft : styles.shiftRight}`} style={{ backgroundColor: isChoice1Active ? "#eb9b30" : "#1464cf" }} > <span className={styles.activeLabel}>{isChoice1Active ? choice1 : choice2}</span> </div> </div> ); }
修改后的CSS代码
@import url("https://fonts.googleapis.com/css?family=Asap:400,500,700"); .container { position: relative; display: inline-flex; border-radius: 0.5rem; overflow: hidden; user-select: none; cursor: pointer; font-family: "Asap", sans-serif; padding: 0.5rem 0; border: 2px solid #e9e9e9; } .labelsContainer { display: flex; width: 100%; } .label { flex: 1; text-align: center; padding: 0 1rem; text-transform: uppercase; font-size: 0.8em; letter-spacing: 0.1em; color: #a9a9a9; } .activeMask { position: absolute; top: 0; bottom: 0; width: 50%; display: flex; align-items: center; justify-content: center; transition: transform 0.3s cubic-bezier(0, 0, 0, 1); color: white; } .activeLabel { text-transform: uppercase; font-size: 0.8em; letter-spacing: 0.1em; } .shiftLeft { transform: translateX(100%); } .shiftRight { transform: translateX(0); } /* 移动端响应式适配 */ @media (max-width: 480px) { .label, .activeLabel { font-size: 0.7em; letter-spacing: 0.05em; padding: 0 0.75rem; } .container { padding: 0.4rem 0; } }
关键优化点说明
- 自适应尺寸:容器使用
inline-flex,宽度由内部文本和padding自动撑开,完美适配不同长度的选项文本 - 结构简化:仅保留底层文本容器和单个遮罩层,避免重复渲染,减少DOM节点数量
- 状态逻辑简化:用布尔值
isChoice1Active管理激活状态,逻辑更直观,降低出错概率 - 响应式适配:通过媒体查询针对小屏幕调整字体大小和内边距,保证移动端交互体验
- 样式可维护性:用CSS类控制遮罩位移,替代内联
clipPath,后续修改样式只需调整CSS即可
内容的提问来源于stack exchange,提问作者shestakov-dev
相关产品推荐
相关产品推荐

