MUI(本稿執筆時v5.4.1)のコンポーネントのスタイルは、ただCSSのクラスを割り当てるだけでは適用できないことが少なくありません。作法にしたがったカスタマイズが必要です。いくつかあるやり方の中から、「Global style overrides」で解説されている、コンポーネントツリーごとにスタイルを上書きする手順と注意についてご説明します。つぎのCodeSandboxのコードがButton
とAccordion
のスタイルをカスタマイズした作例です(2022/02/16にTextField
を追加)。
React + TypeScript: Customizing style of MUI components
Button
のスタイルを替える
まずは、前出「Global style overrides」で紹介されているButton
コンポーネントのコード例です。カスタマイズしたいコンポーネントツリーをThemeProvider
で包みます(なお、「Theme provider」参照)。
そのtheme
プロパティに定めるのが、createTheme()
の戻り値です。引数のオプションオブジェクトには、カスタマイズするのがコンポーネントですので、components
プロパティにコンポーネント名を与えてください。名前(MuiButton
)は、APIリファレンスの「Component name」で調べます。スタイルを上書きするキーがstyleOverrides
です。CSSルールというのはどこに適用するかのキーワードで、やはりAPIリファレンスの「CSS」でお確かめください。CSSの定義の仕方は、基本的にReactのJSXに定めるstyle
と同じです。
つぎのコードで、Button
コンポーネントのテキストカラーが黒、フォントは少し大きめの1remになりました。
import { Button } from '@mui/material';
import { ThemeProvider, createTheme } from '@mui/material/styles';
const theme = createTheme({
components: {
// コンポーネント名
MuiButton: {
styleOverrides: {
// CSSルール名
root: {
// CSS定義
color: 'black',
fontSize: '1rem',
},
},
},
},
});
function App() {
return (
<ThemeProvider theme={theme}>
<Button>font-size: 1rem</Button>
</ThemeProvider>
);
}
export default App;
Accordion
のスタイルを替えるときは注意が必要
Button
コンポーネントのカスタマイズは簡単にできました。厚切りジェイソンなら「OK!パターン見えてきたよ!」と叫ぶところです。ところが、Accordion
で「Why MUI!!」という羽目に。
「Accordion」の「Basic accordion」のコード例で試します。コンポーネント名はMuiAccordion
です。つぎのコードは、追加・修正箇所のみ抜き出しました。たしかにこれで、Accordion
コンポーネントのテキストカラーは青くなるのです。ところが、fontSize: '2rem'
と加えても大きさが変わりません。フォントがらみの変更はきかないようです。
import {
Accordion,
AccordionDetails,
AccordionSummary,
Typography
} from "@mui/material";
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
const theme = createTheme({
components: {
MuiAccordion: {
styleOverrides: {
root: {
color: 'blue',
},
},
},
},
});
function App() {
return (
<ThemeProvider theme={theme}>
<Button>font-size: 1rem</Button>
<div>
<Accordion>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls="panel1a-content"
id="panel1a-header"
>
<Typography>Accordion 1</Typography>
</AccordionSummary>
<AccordionDetails>
<Typography>
{/* ...[略]... */}
</Typography>
</AccordionDetails>
</Accordion>
{/* ...[略]... */}
</div>
</ThemeProvider>
);
}
改めて確かめると、Accordion
は複数のサブパーツから組み立てられています。そこで、カスタマイズの対象をそれらのコンポーネント名に差し替えてみたりもしました。それでも、フォントのスタイルは変わりません。落ち着いてコード例のJSXを見ると、テキストはTypography
コンポーネントに差し込まれています。コンポーネント名をMuiTypography
に書き替えたらビンゴでした(結果は、冒頭のCodeSandbox作例でお確かめください)。
const theme = createTheme({
components: {
MuiTypography: {
styleOverrides: {
root: {
color: 'blue',
fontSize: '2rem',
},
},
},
},
});
MUIコンポーネントのスタイルには、親から子に受け継がれるものもあります。けれど、子コンポーネント独自に保持する場合もあるというのが教訓です。だからといって、JSXの子コンポーネントひとつずつにstyle
プロパティを加えようとしたら、煩雑で管理しにくくなります。コンポーネントツリーをThemeProvider
で包み、theme
で特定のコンポーネントを狙い撃ちして定めるのはスマートでしょう。ただ、仕組みや確かめるべきことの要領がつかめないと、とまどってしまいます。お気をつけください。
[2022/02/16以下追記]
TextField
上部に縮小表示されるlabel
のフォントサイズを大きくしたい
TextField
コンポーネントにlabel
プロパティを定めると、デフォルトではテキストがまずプレースホルダーのようにフィールド内に示され、フォーカスを入れると上部に縮小して表示されます。これがどうも小さく感じられてなりません。日本語は画数が多いからというのも理由です。「憂鬱な薔薇」などと与えた日には、とくに中高年にはつらいものがあるでしょう。
そこで、テキストフィード上部に縮小表示されたラベルのフォントサイズを大きくしたいというのがお題です。ラベルのコンポーネント名はMuiInputLabel
だとわかりました。すると、前述のふたつのコンポーネントと同じく、styleOverridesキ
ーでtheme
を上書きすればたしかにフォントサイズは大きくなります。けれど、それではプレースホルダーのテキストも変わってしまうのです。
縮小表示されたラベルだけスタイルを変えたいという場合には、CSSのルールからshrink
を選んでください。
const theme = createTheme({
components: {
MuiInputLabel: {
styleOverrides: {
shrink: {
fontSize: '1.1rem'
}
}
}
}
});