はじめに
最近、MUIを使ったReactアプリケーションを開発しています。MUIには様々なコンポーネントがありますが、その見た目をカスタマイズする方法を調べました。
Themeとは
MUIはデフォルトでカラーやシャドウ、フォントなどが揃っていて、すぐに使い始めることができる状況となっていますが、実際には開発するサービスの ブランドに合わせて変更する必要が出てくると思います。
そうした場合に、MUIではThemeを設定することで、カラーやシャドウ、フォントなどの見た目を一括管理することができます。
Themeのセットアップ
まずは、Themeを使用できるようにします。App.tsxにThemeProviderコンポーネントを追加し、全てのUIコンポーネントをこの配下に置くようにします。今回は、テーマの変更を確認するためのコンポーネントを配置しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import React, { useContext } from "react"; import "./App.css"; import Button from "@mui/material/Button"; import { createTheme, Snackbar, ThemeProvider } from "@mui/material"; import { themeOptions } from "./theme-options"; function App() { const theme = createTheme(themeOptions); return ( <div className="App"> <ThemeProvider theme={theme}> <Box sx={{ flexGrow: 1 }}> <AppBar position="static"> <Toolbar> <IconButton size="large" edge="start" color="inherit" aria-label="menu" sx={{ mr: 2 }} > <MenuIcon /> </IconButton> <Typography variant="h6" component="div" sx={{ flexGrow: 1 }}> Primary </Typography> <Button color="inherit">Login</Button> </Toolbar> </AppBar> </Box> <Alert severity="info">This is an info alert — check it out!</Alert> <Stack direction="row" spacing={2} m={2}> <Button variant="outlined" color="success"> Success </Button> <Button variant="contained" color="error"> Error </Button> </Stack> <Fab sx={{position: 'absolute', bottom: 16, right: 16}} color="secondary" aria-label="add"> <AddIcon /> </Fab> <Snackbar open={true}> <Alert severity="warning">This is a warning message!</Alert> </Snackbar> </ThemeProvider> </div> ); } export default App; |
次に、theme-options.tsを追加します。
1 2 3 4 5 6 | import { ThemeOptions } from "@mui/material"; import {blue, cyan, green, orange, purple, red} from "@mui/material/colors"; export const themeOptions: ThemeOptions = { // ここでテーマをカスタマイズします。 }; |
Themeの設定方法
よく使うと思われる、Pallete、Elevationのシャドウ、タイポグラフィー、そしてコンポーネントの設定方法を説明します。
Palette
コンポーネントで使用されるカラーを変更します。
colorオブジェクト
colorオブジェクトを使うと、あらかじめ用意されているパレットからカラーを変更することができます。ColorはこちらのHUEを選択します。(SHADEは指定することができず、Paletteが自動的に指定します。)
1 2 3 4 5 6 7 8 9 10 11 12 13 | import { ThemeOptions } from "@mui/material"; import {blue, cyan, deepPurple, green, orange, red} from "@mui/material/colors"; export const themeOptions: ThemeOptions = { palette: { primary: blue, secondary: deepPurple, error: red, warning: orange, info: cyan, success: green }, }; |
直接色を指定する
colorオブジェクトでの色指定では、main, light, dark, contrastTextを個別で指定することはできません。その場合、直接色を指定することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import { ThemeOptions } from "@mui/material"; import {cyan, green, orange, red} from "@mui/material/colors"; export const themeOptions: ThemeOptions = { palette: { primary: { main: orange[900], }, secondary: { light: '#0066ff', main: '#0044ff', contrastText: '#ffcc00', }, error: red, warning: orange, info: cyan, success: green, contrastThreshold: 3, totalOffset: 0.2, }, }; |
primaryはmainしか指定していませんが、light dark contrastTextは、mainの色から計算されます。secondaryではdarkが指定されていませんが、mainの色から計算されます。
また、色の指定方法として、colorsから指定する方法と、カラーコードでの指定方法があります。MUIを使用している以上、colorsにある色から、HUEとSHADEを指定する方法がおすすめです。
contrastThresholdとtotalOffsetは必須ではありませんが、main以外の色の計算結果をカスタマイズするのに使用できます。contrastThresholdは、contrastTextの色の計算時に使用される閾値です。
totalOffsetは、0.0~1.0の間で指定し、値を大きくすればするほど、lightがより明るくなり、darkがより暗くなります。
Elevationのシャドウ
Eevationすると入るシャドウは、shadowsで設定します。shadowsは25個の配列で、0個目は必ず’none’を指定しますが、それ以外はelevationの1~25の段階ごとにshadowの設定をします。shadowは、CSSのbox-shadowの指定方法と同じです。
シャドウを完全に無くすには次のようにします。
1 2 3 4 5 6 7 | import { ThemeOptions } from "@mui/material"; import {cyan, green, orange, red} from "@mui/material/colors"; import shadows, {Shadows} from "@mui/material/styles/shadows"; export const themeOptions: ThemeOptions = { shadows: shadows.map(() => 'none') as Shadows }; |
タイポグラフィー
Font FamilyやFont Sizeを変更することができます。
1 2 3 4 5 6 7 8 | import { ThemeOptions } from "@mui/material"; export const themeOptions: ThemeOptions = { typography: { fontFamily: ["Yu Gothic", 'Roboto', "sans-serif"].join(','), fontSize: 14 } }; |
fontFamily
はカンマ区切りの文字列で指定しますが、可読性を上げるために配列をjoinしています。
fontSize
は、MUIの各コンポーネントで使用されるフォントサイズを計算するのに使用されます。defaultは14pxですが、日本語や中国語などはフォントが大きいため、小さ目の数値にすると可読性が増すとのことです。
コンポーネント
MUIで用意されているコンポーネントごとのスタイルを上書きすることができます。
Default Props
コンポーネントのデフォルト値を指定することもできます。例えば、TextFieldコンポーネントのvariantはデフォルトでOutlinedになっていますが、アプリケーション全体でStandardを使いたい指定したい場合、次のように指定できます。
1 2 3 4 5 6 7 8 9 10 11 | import { ThemeOptions } from "@mui/material"; export const themeOptions: ThemeOptions = { components: { MuiTextField: { defaultProps: { variant: "standard" } } } }; |
Style Overrides
コンポーネントのスタイルを上書きすることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import { ThemeOptions } from "@mui/material"; import {cyan, green, orange, red} from "@mui/material/colors"; export const themeOptions: ThemeOptions = { components: { MuiButton: { styleOverrides: { root: { fontSize: '2rem' } } } } }; |
root
となっている部分は、そのコンポーネントのスロットとなります。この部分はコンポーネントのDOMツリーによって異なっていて、例えばButtonであればアイコン表示時のサイズを指定できる
iconSizeMedium
があったりします。
他にも、Menuであれば
paper
というスロットがあり、こちらはMenuコンポーネントに内包されるPaperのスタイルを定義することができます。
Buttonの場合は、次のようなスロットがあります。
- root: ルートエレメントに適用
- text: variant=”text” かつ color=”inherit” のときに、ルートエレメントに適用
- iconSizeMedium: size=”medium”のときに、iconエレメントに適用
MUI Theme Creator
おまけとして、便利なツールを紹介します。
MUI Theme Creator
https://bareynol.github.io/mui-theme-creator/
このツールを使用すると、MUIのテーマをプレビューしながら作ることができます。変更した内容は、ThemeOptionsのソースに反映されていくため、そのままコピペで使うことができます。
さいごに
Themeを使うと、MUIの見た目に関する設定を一括管理できることが分かりました。それでは良いMUIライフを!