2021年09月20日
MUI (Material-UI) v5 のスタイリング方法
2021年9月16日に MUI (Material-UI) v5 が正式にリリースされました 。 Material-UI v4 のリリース が 2019年3月なので、約2年半ぶりのメジャーアップデートです。 正式名称が Material-UI から MUI に変更になり 、パッケージ名も @material-ui/*
から @mui/*
になりました。
MUI v5 ではコンポーネントのスタイリングの実装方法や記法が一新し、Material-UI v4 以前までの独特な記法から、 Theme UI 、 chakra などで用いられている sx
Prop によるスタイリングになりました。
大幅な変更になるので、v4 からの移行コストは大きいですが、新たに MUI を学ぶ人には優しくなった印象です。
MUI v5 のスタイリング方法を v4 の記法と比較しながら紹介していきます。
yarn add @mui/material @emotion/react @emotion/styled
スタイリングの実装方法
MUI v5 では、スタイリングのコアライブラリが JSS から emotion に変わりました。この記事では説明しないので、詳しく知りたい方は Introducing MUI Core v5.0 を参照してください。
さて、v4 では useStyles
という自作フックでコンポーネントのスタイリングをしていましたが、この変更によって v5 からはコンポーネントに sx
Prop で直接スタイルを書くことができます。
v4 と v5 の記法の違い
Material-UI v4 の記法
makeStyles
でスタイル用のフックを作成し、コンポーネント内で className を取得します。
import { makeStyles, createStyles } from "@material-ui/core/styles";
// フックを作成
const useStyles = makeStyles((theme) =>
createStyles({
root: {
color: theme.palette.primary.main,
padding: theme.spacing(2),
},
}),
);
function Hoge() {
// フックで className を取得
const classes = useStyles();
return <div className={classes.root}>Hoge</div>;
}
MUI v5 の記法
sx
Prop にスタイルを直接記入します。
import Box from "@mui/material/Box";
function Hoge() {
return <Box sx={{ color: "primary.main", p: 2 }}>Hoge</Box>;
}
sx
Prop によって記述量がとても少なくなり、初心者にもわかりやすい記法になりました。
color に指定した primary.main
は、MUI テーマのパレットを利用する方法です。 v5 で新たに導入されたこの記法 では、theme
を引数に取る関数(後述)を指定しなくても MUI テーマのパレットを利用することができます。
sx
Prop について
MUI v5 のすべてのコンポーネントは sx
Prop でスタイリング可能です。sx
Prop は従来の(React では非推奨ですが)style
Prop に似ていますが、 MUI テーマに基づいたスタイリング や、 レスポンシブで動的なスタイリング が容易という特徴があります。
<Box
sx={{
width: {
xs: 100, // theme.breakpoints.up('xs')
sm: 200, // theme.breakpoints.up('sm')
md: 300, // theme.breakpoints.up('md')
lg: 400, // theme.breakpoints.up('lg')
xl: 500, // theme.breakpoints.up('xl')
},
height: (theme) => theme.spacing(10), // => 80px (8px * 10)
}}
>
This box has a responsive width.
</Box>
sx
Prop では、v4 の makeStyle
によるスタイリングと同様に、値にtheme
を引数にとった関数を指定することができます。
<Box>
コンポーネントについて
<Box>
コンポーネント は、sx
Prop のプロパティを Prop として直接記述できる基礎的なコンポーネントです。実は v4 時代には既に導入されていました が、パフォーマンスが低いという難点がありました。リリースノートによると、v5 では大幅にパフォーマンスが改善されたそうです。
import Box from "@mui/material/Box";
// padding: 16px (spacing(8px) * 2)
// background-color: theme.palette.primary.dark
<Box p={2} bgcolor="primary.dark" width={100} height={100}>
hoge
</Box>;
<Box>
コンポーネントと <Typography>
コンポーネントではこの方法で、 sx
Prop を使わずにスタイルを設定することができます。
<Box>
Component 一般の HTML 要素のスタイリング
<div>
や <span>
などの一般の HTML 要素は sx
Prop を持ちません。これらをスタイリングするには、<Box>
コンポーネント や <Typography>
コンポーネントを使い、component
Prop で HTML 要素を指定するといいでしょう。
import Box from "@mui/material/Box";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
interface ItemProps {
children: React.ReactNode;
}
function Item({ children }: ItemProps) {
return (
<Typography
variant="body2"
component="span"
sx={{ backgroundColor: "secondary.light", p: 1 }}
>
{children}
</Typography>
);
}
function Hoge() {
return (
// py (padding-top, padding-bottom): { xs: 16px, sm: 8px }
<Box component="nav" sx={{ py: [2, 1] }}>
<Stack spacing={2} direction={{ xs: "column", sm: "row" }}>
<Item>Top</Item>
<Item>News</Item>
<Item>Site Map</Item>
</Stack>
</Box>
);
}
<Box>
Component <Typography>
Component margin, padding と spacing
という単位
MUI にはスタイリングの統一感を出すために、padding や margin に指定するための spacing
という単位が存在します。spacing
は MUI テーマ で規定されていて、デフォルトでは 8px に設定されています。
sx
Prop や <Box>
コンポーネントで設定する padding や margin には、spacing
が単位として使われています。v4 では makeStyles
でフックを作る際に、theme.spacing
を使うことで spacing
の単位が明示的に使われていましたが、v5 になって spacing
という単位が暗黙的に使われるようになったので注意が必要です。
// margin-right: 8px (8px * 1)
<Typography component="span" sx={{ mr: 1 }}></Typography>
// padding-top, paading-bottom: 16px (8px * 2)
<Box py={2}></Box>
また、padding と margin だけは spacing
を単位に取りますが、その他のプロパティは基本的に px
を単位に取るので混同しないように注意が必要です。また、borderRadius
は独自の theme.shape.borderRadius
(デフォルトは spacing
の半分である 4px)という単位を取るので注意しましょう。
// 正円になる
<Box sx={{
display: 'flex',
width: 64, // => 64px
height: 64, // => 64px
borderRadius: 8, // => 32px (4px * 8)
}} />
<Box sx={{
display: 'flex',
width: (theme) => theme.spacing(8), // 64px
height: (theme) => theme.spacing(8), // 64px
borderRadius: 8, // 32px (4px * 8)
}} />
感想
v3 以前の withStyles
、v4 の makeStyles
といった Material-UI 特有の記法は Material-UI 入門者にはやや難解な印象がありました。
v5 では sx
Prop で記述する形になったので、初心者にはわかりやすくなったものの、パレットカラーの記法や、padding, margin における spacing
の暗黙的な利用など、覚えなくてはいけない事柄は増えた印象です。とはいえ、この辺りはおそらく Theme UI や Tailwind CSS でも同じことでしょう。
MUI v5 のスタイリングの触りの部分だけをざっと説明しました。
この先は 公式ドキュメント 、特に MUI System の項を熟読することをお勧めします。
参考
- MUI
- Introducing MUI Core v5.0
- Migration from v4 to v5
- Material-UI v5を先取りする - Techtouch Developers Blog
雨のぼり / セカイイチ (2005)
Material-UI
Material-UI (MUI)はGoogleのマテリアルデザインをReactで実装するUIライブラリです。
https://mui.com/