如何在React(TSX)中创建带有示例样式阴影的3D效果按钮?
如何在React(TSX)中创建带有示例样式阴影的3D效果按钮?
嘿,刚好我之前折腾过类似的3D按钮效果,给你分享一个React TSX的实现方案,用CSS的多层阴影和状态切换就能完美还原你要的这种凸起质感,上手超简单!
核心思路其实很直观:这种3D效果主要靠多层偏移的box-shadow模拟按钮的侧边和底部厚度,再配合按压状态的样式切换,做出按下时的凹陷反馈,让交互感拉满。
话不多说,直接上可运行的TSX代码:
import { useState } from 'react'; // 定义按钮组件的Props类型,符合TSX的类型规范 interface ThreeDButtonProps { children: React.ReactNode; onClick?: () => void; } const ThreeDButton = ({ children, onClick }: ThreeDButtonProps) => { // 用状态跟踪按钮的按压状态 const [isPressed, setIsPressed] = useState(false); // 核心3D样式,根据按压状态切换 const buttonStyles = { base: { // 基础布局样式,可按需调整 padding: '12px 28px', fontSize: '17px', fontWeight: '600', border: 'none', cursor: 'pointer', position: 'relative', // 正面颜色,接近示例的绿色,也可以换渐变增强质感 backgroundColor: '#2ecc71', // backgroundColor: 'linear-gradient(145deg, #2ecc71, #27ae60)', // 带光泽的渐变版本 color: '#ffffff', borderRadius: '4px', transition: 'all 0.12s ease-out', // 未按压时的外阴影:多层偏移模拟3D厚度 boxShadow: isPressed ? 'inset 3px 3px 4px rgba(0, 0, 0, 0.25), inset -3px -3px 4px rgba(0, 0, 0, 0.15)' : '3px 3px 0px rgba(0, 0, 0, 0.22), 6px 6px 0px rgba(0, 0, 0, 0.18), 9px 9px 0px rgba(0, 0, 0, 0.12)', // 按压时偏移位置,模拟按下的凹陷 transform: isPressed ? 'translate(3px, 3px)' : 'translate(0, 0)', }, }; return ( <button style={buttonStyles.base} // 处理点击事件,同时同步按压状态的超时重置 onClick={(e) => { setIsPressed(true); setTimeout(() => setIsPressed(false), 120); onClick?.(e); }} // 处理鼠标按下/抬起/离开事件,确保状态正确 onMouseDown={() => setIsPressed(true)} onMouseUp={() => setIsPressed(false)} onMouseLeave={() => setIsPressed(false)} > {children} </button> ); }; // 组件使用示例,直接在App里引入即可 const App = () => { return ( <div style={{ padding: '60px', display: 'flex', justifyContent: 'center' }}> <ThreeDButton onClick={() => alert('按钮触发成功!')}> 点击我试试 </ThreeDButton> </div> ); }; export default App;
给你拆解几个关键细节,方便你自定义调整:
- 3D厚度控制:未按压时的box-shadow每一层的x、y偏移量决定了厚度,如果你想要更厚的3D效果,把3px、6px、9px改成更大的数值就行,阴影颜色的透明度也可以调整,让层次更自然。
- 按压反馈优化:transition的时长可以根据你的交互偏好调整,0.12s是比较紧凑的反馈,换成0.15s会更平缓。
- 质感升级:给按钮正面加线性渐变的话,会比单一颜色更接近示例的光泽感,只需要把backgroundColor换成渐变就行(记得在style里用
background,不是backgroundColor)。
最后提个小坑:如果你的项目用了CSS模块或者Tailwind,也可以把样式抽成类名,写法更灵活,核心逻辑还是多层阴影+状态切换这一套~
备注:内容来源于stack exchange,提问作者Joey Bennedict
相关产品推荐
相关产品推荐

