カテゴリー: FrontEnd

MUI Themeでカラー、シャドウ、フォントなどを設定する

はじめに

最近、MUIを使ったReactアプリケーションを開発しています。MUIには様々なコンポーネントがありますが、その見た目をカスタマイズする方法を調べました。

Themeとは

MUIはデフォルトでカラーやシャドウ、フォントなどが揃っていて、すぐに使い始めることができる状況となっていますが、実際には開発するサービスの ブランドに合わせて変更する必要が出てくると思います。
そうした場合に、MUIではThemeを設定することで、カラーやシャドウ、フォントなどの見た目を一括管理することができます。

Themeのセットアップ

まずは、Themeを使用できるようにします。App.tsxにThemeProviderコンポーネントを追加し、全てのUIコンポーネントをこの配下に置くようにします。今回は、テーマの変更を確認するためのコンポーネントを配置しています。

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を追加します。

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が自動的に指定します。)

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を個別で指定することはできません。その場合、直接色を指定することができます。

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の指定方法と同じです。
シャドウを完全に無くすには次のようにします。

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を変更することができます。

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を使いたい指定したい場合、次のように指定できます。

import { ThemeOptions } from "@mui/material";

export const themeOptions: ThemeOptions = {
  components: {
    MuiTextField: {
      defaultProps: {
        variant: "standard"
      }
    }
  }
};

Style Overrides

コンポーネントのスタイルを上書きすることができます。

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ライフを!

おすすめ書籍

カイザー

シェア
執筆者:
カイザー
タグ: ReactTypeScript

最近の投稿

フロントエンドで動画デコレーション&レンダリング

はじめに 今回は、以下のように…

2週間 前

Goのクエリビルダー goqu を使ってみる

はじめに 最近携わっているとあ…

3週間 前

【Xcode15】プライバシーマニフェスト対応に備えて

はじめに こんにちは、suzu…

2か月 前

FSMを使った状態管理をGoで実装する

はじめに 一般的なアプリケーシ…

3か月 前