如何用styled-components为不同父元素的Material UI DatePicker设置样式
问题:Material UI DatePicker弹窗样式无法通过styled-components生效?
我在使用Material UI时发现:DatePicker组件包含TextField组件,点击图标会打开日历弹窗。通过开发者工具可见,TextField的父元素是<div id='root'>,但日历弹窗的父元素是<body>。我尝试通过styled-components改写DatePicker的样式(代码如下),但不知道如何通过DatePicker组件为弹窗应用CSS样式,请问这是否可行?
现有代码
demo.js
import * as React from "react"; import TextField from "@mui/material/TextField"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { DatePickerStyled } from "./styles"; export default function BasicDatePicker() { const [value, setValue] = React.useState(null); return ( <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePickerStyled label="Basic example" value={value} onChange={(newValue) => { setValue(newValue); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> ); }
styles.js
import styled from "styled-components"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; export const DatePickerStyled = styled(DatePicker)` & .MuiPickersPopper-root { & .MuiPickersPopper-root { border: 4px solid red; position: absolute; left: -23px; top: 4px; right: 0; } } `; DatePickerStyled.displayName = "DatePickerStyled";
解决方案
原写法无法生效的核心原因:日历弹窗被挂载到了<body>节点下,脱离了DatePicker组件的DOM层级,而styled-components的样式是作用在DatePicker本身的,无法穿透到全局层级的弹窗元素。
以下是两种可行的实现方式:
方法1:使用Material UI主题系统(推荐)
通过createTheme自定义全局组件样式,精准控制弹窗样式:
import * as React from "react"; import TextField from "@mui/material/TextField"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { createTheme, ThemeProvider } from '@mui/material/styles'; // 自定义主题,覆盖弹窗样式 const theme = createTheme({ components: { MuiPickersPopper: { styleOverrides: { root: { border: '4px solid red', position: 'absolute', left: '-23px', top: '4px', right: '0', }, }, }, }, }); export default function BasicDatePicker() { const [value, setValue] = React.useState(null); return ( <ThemeProvider theme={theme}> <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePicker label="Basic example" value={value} onChange={(newValue) => { setValue(newValue); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> </ThemeProvider> ); }
方法2:使用styled-components全局样式(不推荐)
通过createGlobalStyle直接给全局类名添加样式,注意会影响所有同类型弹窗:
import * as React from "react"; import TextField from "@mui/material/TextField"; import { AdapterDateFns } from "@mui/x-date-pickers/AdapterDateFns"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import styled, { createGlobalStyle } from "styled-components"; // 全局样式 const GlobalDatePickerStyle = createGlobalStyle` .MuiPickersPopper-root { border: 4px solid red; position: absolute; left: -23px; top: 4px; right: 0; } `; export default function BasicDatePicker() { const [value, setValue] = React.useState(null); return ( <> <GlobalDatePickerStyle /> <LocalizationProvider dateAdapter={AdapterDateFns}> <DatePicker label="Basic example" value={value} onChange={(newValue) => { setValue(newValue); }} renderInput={(params) => <TextField {...params} />} /> </LocalizationProvider> </> ); }
内容的提问来源于stack exchange,提问作者Happy1234
相关产品推荐
相关产品推荐

