You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 01:05:33