为@mui/material TextField添加endAdornment后自定义样式失效
问题
使用MUI官网示例中的CSS验证样式TextField,仅添加endAdornment后自定义样式完全失效。测试发现添加普通HTML元素时样式正常,但加入IconButton这类MUI组件时样式失效,请问是否需要额外配置或这是组件bug?
代码示例:
import * as React from "react"; import { styled } from "@mui/material/styles"; import Box from "@mui/material/Box"; import TextField from "@mui/material/TextField"; import { IconButton } from "@mui/material"; import ClearIcon from "@mui/icons-material/Clear"; const ValidationTextField = styled(TextField)({ "& input:valid + fieldset": { borderColor: "green", borderWidth: 2 }, "& input:invalid + fieldset": { borderColor: "red", borderWidth: 2 }, "& input:valid:focus + fieldset": { borderLeftWidth: 6, padding: "4px !important" // override inline-style } }); export default function CustomizedInputs() { return ( <Box component="form" noValidate sx={{ display: "grid", gridTemplateColumns: { sm: "1fr 1fr" }, gap: 2 }} > <ValidationTextField label="CSS validation style" required variant="outlined" defaultValue="Success" id="validation-outlined-input" /> <ValidationTextField label="CSS validation style" required variant="outlined" defaultValue="Success" id="validation-outlined-input" InputProps={{ endAdornment: ( <> <IconButton> <ClearIcon /> </IconButton> </> ) }} /> </Box> ); }
解决方案
这不是组件bug,是DOM结构变化导致CSS选择器失效。
原样式使用的+是相邻兄弟选择器,要求input元素必须紧跟fieldset元素才能匹配。但添加IconButton作为endAdornment时,MUI会在input和fieldset之间插入.MuiInputAdornment-root容器,破坏了两者的相邻关系,导致选择器无法命中fieldset。
修改方案很简单,把相邻兄弟选择器+替换为通用兄弟选择器~,它能匹配input之后所有的fieldset兄弟元素,不受中间插入元素影响:
const ValidationTextField = styled(TextField)({ "& input:valid ~ fieldset": { borderColor: "green", borderWidth: 2 }, "& input:invalid ~ fieldset": { borderColor: "red", borderWidth: 2 }, "& input:valid:focus ~ fieldset": { borderLeftWidth: 6, padding: "4px !important" // 覆盖内联样式 } });
如果需要更精准的匹配(比如避免影响其他可能的fieldset),也可以使用:has()选择器(现代浏览器支持),通过父元素来定位fieldset:
const ValidationTextField = styled(TextField)({ "&:has(input:valid) fieldset": { borderColor: "green", borderWidth: 2 }, "&:has(input:invalid) fieldset": { borderColor: "red", borderWidth: 2 }, "&:has(input:valid:focus) fieldset": { borderLeftWidth: 6, padding: "4px !important" } });
修改后,无论是否添加endAdornment,自定义验证样式都能正常生效。
内容的提问来源于stack exchange,提问作者Stefan Meindl
相关产品推荐
相关产品推荐

