Material-UI 主题基础 #

什么是主题? #

主题是一组设计规范的集合,包括颜色、排版、间距、形状等。MUI 的主题系统让你可以统一管理应用的视觉风格。

text
┌─────────────────────────────────────────┐
│              MUI 主题结构                │
├─────────────────────────────────────────┤
│                                         │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐│
│  │ palette │  │typography│  │ spacing ││
│  │  调色板  │  │  排版    │  │  间距   ││
│  └─────────┘  └─────────┘  └─────────┘│
│                                         │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐│
│  │breakpoints│ │ shape  │  │ shadows ││
│  │  断点    │  │  形状   │  │  阴影   ││
│  └─────────┘  └─────────┘  └─────────┘│
│                                         │
│  ┌─────────┐  ┌─────────┐             │
│  │transitions│ │components│             │
│  │  过渡    │  │ 组件定制 │             │
│  └─────────┘  └─────────┘             │
│                                         │
└─────────────────────────────────────────┘

创建主题 #

基础主题 #

jsx
import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme();

function App() {
  return (
    <ThemeProvider theme={theme}>
      <YourApp />
    </ThemeProvider>
  );
}

自定义主题 #

jsx
const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
    secondary: {
      main: '#dc004e',
    },
  },
  typography: {
    fontFamily: 'Roboto, Arial, sans-serif',
  },
});

调色板(Palette) #

颜色类型 #

MUI 提供多种颜色类型:

jsx
const theme = createTheme({
  palette: {
    primary: {
      main: '#1976d2',
      light: '#42a5f5',
      dark: '#1565c0',
      contrastText: '#fff',
    },
    secondary: {
      main: '#dc004e',
      light: '#ff4081',
      dark: '#c51162',
      contrastText: '#fff',
    },
    error: {
      main: '#f44336',
      light: '#e57373',
      dark: '#d32f2f',
    },
    warning: {
      main: '#ff9800',
      light: '#ffb74d',
      dark: '#f57c00',
    },
    info: {
      main: '#2196f3',
      light: '#64b5f6',
      dark: '#1976d2',
    },
    success: {
      main: '#4caf50',
      light: '#81c784',
      dark: '#388e3c',
    },
  },
});

深色模式 #

jsx
const theme = createTheme({
  palette: {
    mode: 'dark',
    primary: {
      main: '#90caf9',
    },
    secondary: {
      main: '#f48fb1',
    },
    background: {
      default: '#121212',
      paper: '#1e1e1e',
    },
  },
});

动态切换主题 #

jsx
import { useState } from 'react';
import { createTheme, ThemeProvider, useTheme } from '@mui/material/styles';
import { CssBaseline, Button } from '@mui/material';

function App() {
  const [darkMode, setDarkMode] = useState(false);

  const theme = createTheme({
    palette: {
      mode: darkMode ? 'dark' : 'light',
      primary: {
        main: '#1976d2',
      },
    },
  });

  return (
    <ThemeProvider theme={theme}>
      <CssBaseline />
      <Button onClick={() => setDarkMode(!darkMode)}>
        切换到{darkMode ? '浅色' : '深色'}模式
      </Button>
    </ThemeProvider>
  );
}

使用内置颜色 #

MUI 提供了 Material Design 的标准颜色:

jsx
import { blue, pink, green } from '@mui/material/colors';

const theme = createTheme({
  palette: {
    primary: blue,
    secondary: pink,
    success: green,
  },
});

排版(Typography) #

字体家族 #

jsx
const theme = createTheme({
  typography: {
    fontFamily: [
      '-apple-system',
      'BlinkMacSystemFont',
      '"Segoe UI"',
      'Roboto',
      '"Helvetica Neue"',
      'Arial',
      'sans-serif',
    ].join(','),
  },
});

字体变体 #

jsx
const theme = createTheme({
  typography: {
    h1: {
      fontSize: '2.5rem',
      fontWeight: 500,
      lineHeight: 1.2,
    },
    h2: {
      fontSize: '2rem',
      fontWeight: 500,
    },
    h3: {
      fontSize: '1.75rem',
      fontWeight: 500,
    },
    h4: {
      fontSize: '1.5rem',
      fontWeight: 500,
    },
    h5: {
      fontSize: '1.25rem',
      fontWeight: 500,
    },
    h6: {
      fontSize: '1rem',
      fontWeight: 500,
    },
    subtitle1: {
      fontSize: '1rem',
      fontWeight: 400,
    },
    subtitle2: {
      fontSize: '0.875rem',
      fontWeight: 500,
    },
    body1: {
      fontSize: '1rem',
      lineHeight: 1.5,
    },
    body2: {
      fontSize: '0.875rem',
      lineHeight: 1.5,
    },
    button: {
      textTransform: 'none',
    },
    caption: {
      fontSize: '0.75rem',
    },
    overline: {
      fontSize: '0.75rem',
      textTransform: 'uppercase',
    },
  },
});

使用排版 #

jsx
function TypographyExample() {
  return (
    <div>
      <Typography variant="h1">H1 标题</Typography>
      <Typography variant="h2">H2 标题</Typography>
      <Typography variant="body1">正文内容</Typography>
      <Typography variant="caption">说明文字</Typography>
    </div>
  );
}

间距(Spacing) #

MUI 使用 8px 为基础单位:

jsx
const theme = createTheme({
  spacing: 8,
});

使用间距 #

jsx
<Box sx={{ p: 2 }}>
  padding: 16px (8 * 2)
</Box>

<Box sx={{ m: 3 }}>
  margin: 24px (8 * 3)
</Box>

<Box sx={{ p: 1.5 }}>
  padding: 12px (8 * 1.5)
</Box>

自定义间距函数 #

jsx
const theme = createTheme({
  spacing: (factor) => `${0.5 * factor}rem`,
});

断点(Breakpoints) #

默认断点 #

jsx
const theme = createTheme({
  breakpoints: {
    values: {
      xs: 0,
      sm: 600,
      md: 900,
      lg: 1200,
      xl: 1536,
    },
  },
});

使用断点 #

jsx
<Box
  sx={{
    width: {
      xs: '100%',
      sm: '80%',
      md: '60%',
      lg: '50%',
      xl: '40%',
    },
    p: {
      xs: 1,
      sm: 2,
      md: 3,
    },
  }}
>
  响应式 Box
</Box>

useMediaQuery #

jsx
import { useMediaQuery, useTheme } from '@mui/material';

function ResponsiveComponent() {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
  const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md'));
  const isDesktop = useMediaQuery(theme.breakpoints.up('md'));

  return (
    <div>
      {isMobile && <MobileView />}
      {isTablet && <TabletView />}
      {isDesktop && <DesktopView />}
    </div>
  );
}

形状(Shape) #

圆角 #

jsx
const theme = createTheme({
  shape: {
    borderRadius: 8,
  },
});

使用形状 #

jsx
<Box sx={{ borderRadius: 1 }}>
  borderRadius: 8px
</Box>

<Box sx={{ borderRadius: 2 }}>
  borderRadius: 16px
</Box>

<Box sx={{ borderRadius: '50%' }}>
  圆形
</Box>

阴影(Shadows) #

默认阴影 #

jsx
<Box sx={{ boxShadow: 1 }}>阴影级别 1</Box>
<Box sx={{ boxShadow: 2 }}>阴影级别 2</Box>
<Box sx={{ boxShadow: 3 }}>阴影级别 3</Box>
<Box sx={{ boxShadow: 4 }}>阴影级别 4</Box>
<Box sx={{ boxShadow: 5 }}>阴影级别 5</Box>

自定义阴影 #

jsx
const theme = createTheme({
  shadows: [
    'none',
    '0px 2px 1px -1px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 1px 3px 0px rgba(0,0,0,0.12)',
  ],
});

组件定制 #

全局定制 #

jsx
const theme = createTheme({
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: 8,
          textTransform: 'none',
        },
      },
    },
    MuiTextField: {
      styleOverrides: {
        root: {
          marginBottom: 16,
        },
      },
    },
  },
});

变体定制 #

jsx
const theme = createTheme({
  components: {
    MuiButton: {
      variants: [
        {
          props: { variant: 'gradient' },
          style: {
            background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)',
            border: 0,
            borderRadius: 3,
            boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)',
            color: 'white',
          },
        },
      ],
    },
  },
});

<Button variant="gradient">渐变按钮</Button>

默认属性 #

jsx
const theme = createTheme({
  components: {
    MuiButton: {
      defaultProps: {
        variant: 'contained',
        color: 'primary',
      },
    },
    MuiTextField: {
      defaultProps: {
        variant: 'outlined',
        size: 'small',
      },
    },
  },
});

访问主题 #

useTheme Hook #

jsx
import { useTheme } from '@mui/material/styles';

function MyComponent() {
  const theme = useTheme();

  return (
    <Box sx={{ color: theme.palette.primary.main }}>
      主色调文字
    </Box>
  );
}

styled API #

jsx
import { styled } from '@mui/material/styles';

const MyButton = styled('button')(({ theme }) => ({
  padding: theme.spacing(1, 2),
  backgroundColor: theme.palette.primary.main,
  color: theme.palette.primary.contrastText,
  borderRadius: theme.shape.borderRadius,
  '&:hover': {
    backgroundColor: theme.palette.primary.dark,
  },
}));

sx prop #

jsx
<Box
  sx={{
    p: 2,
    bgcolor: 'primary.main',
    color: 'primary.contrastText',
    borderRadius: 1,
  }}
>
  使用主题值
</Box>

主题工具函数 #

responsiveFontSizes #

jsx
import { createTheme, responsiveFontSizes } from '@mui/material/styles';

let theme = createTheme();
theme = responsiveFontSizes(theme);

createMuiTheme(已弃用) #

jsx
import { createTheme } from '@mui/material/styles';

const theme = createTheme({
});

完整主题示例 #

jsx
import { createTheme } from '@mui/material/styles';
import { blue, pink } from '@mui/material/colors';

const theme = createTheme({
  palette: {
    mode: 'light',
    primary: {
      main: blue[500],
      light: blue[300],
      dark: blue[700],
    },
    secondary: {
      main: pink[500],
      light: pink[300],
      dark: pink[700],
    },
    background: {
      default: '#fafafa',
      paper: '#ffffff',
    },
  },
  typography: {
    fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
    h1: {
      fontSize: '2.5rem',
      fontWeight: 500,
    },
    h2: {
      fontSize: '2rem',
      fontWeight: 500,
    },
    h3: {
      fontSize: '1.75rem',
      fontWeight: 500,
    },
    button: {
      textTransform: 'none',
    },
  },
  spacing: 8,
  shape: {
    borderRadius: 8,
  },
  breakpoints: {
    values: {
      xs: 0,
      sm: 600,
      md: 900,
      lg: 1200,
      xl: 1536,
    },
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          borderRadius: 8,
        },
      },
    },
    MuiCard: {
      styleOverrides: {
        root: {
          boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
        },
      },
    },
  },
});

export default theme;

下一步 #

现在你已经掌握了主题基础,继续学习 布局组件,深入了解 MUI 的布局系统!

最后更新:2026-03-28