Material UI emotion/styled 如何组合多段CSS类实现条件样式
Material UI 新版styled API 条件样式实现方案
首先明确:完全不需要强制依赖sx属性实现条件样式,sx只是官方提供的可选写法之一,新版API原生支持多种条件样式实现方式,完全可以覆盖旧版makeStyles+className拼接的所有场景,常用写法如下:
- 方式1:给styled组件传自定义props,在样式定义内做条件判断
这是和styled-components生态完全对齐的原生写法,MUI的styled工具会自动过滤非DOM标准的自定义props,不会产生无效属性透传的控制台警告,适合抽离可复用组件时使用,对应高对比度样式场景的示例代码:
import { styled, Input } from '@mui/material'; import { useState } from 'react'; // 定义组件时直接接收自定义props和theme做判断 const StyledInput = styled(Input)<{ highContrast?: boolean }>(({ theme, highContrast }) => ({ width: '100%', // 条件成立时追加对应样式 ...(highContrast && { color: theme.palette.getContrastText(theme.palette.primary.main), }) })); function MyComp() { const [highContrast, setHighContrast] = useState(false); // 直接把业务状态作为props传入即可 return <StyledInput highContrast={highContrast} value={100} /> }
- 方式2:沿用className拼接逻辑,和v4写法体验一致
新版MUI组件完全支持className属性传入,依然可以用clsx/classnames这类工具类库做条件类名拼接,只需要在styled定义时把对应类名的样式写在选择器里即可,适合从v4迁移的项目快速适配:
import { styled, Input } from '@mui/material'; import { useState } from 'react'; import clsx from 'clsx'; const StyledInput = styled(Input)(({ theme }) => ({ width: '100%', '&.root-light': { color: theme.palette.getContrastText(theme.palette.primary.main), } })); function MyComp() { const [highContrast, setHighContrast] = useState(false); return <StyledInput className={clsx({ 'root-light': highContrast })} value={100} /> }
- 方式3:使用sx属性写内联条件样式(可选非必须)
sx属性的优势是写单次使用、逻辑简单的内联样式时不需要额外抽离styled组件,开发效率更高,但它的运行性能略低于提前定义好的styled组件,更适合非复用的零散场景:
import { Input } from '@mui/material'; import { useState } from 'react'; function MyComp() { const [highContrast, setHighContrast] = useState(false); return <Input value={100} sx={{ width: '100%', color: highContrast ? 'primary.contrastText' : undefined }} /> }
实际开发中可以根据场景灵活选择:抽离公共复用组件优先用styled+props传参的写法,迁移旧项目可以沿用className拼接逻辑,简单单页场景用sx快速实现即可,不存在“所有条件样式必须用sx”的强制要求。
内容的提问来源于stack exchange,提问作者paul23
相关产品推荐
相关产品推荐

