フロントエンドのスタイリングについて、考えた時にUIライブラリとして候補に上がってくるMaterial UI (MUI)
を触ってみて基礎的な内容と、感じたことをメモで残しました。
この記事の対象者
- cssの基本的な文法は分かる
- MUIを使ってみようと思っているが、使うイメージが全然わかない人
- MUI の文法の基礎を知りたい人
環境
シンプルに npx create-react-app アプリ名
で生成した状態です。
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@mui/material": "^5.15.21",
"react": "^18.3.1",
}
Container
コンテンツを水平方向に中央揃えでき、最も基本的なレイアウト要素になる。
デフォルトで左右にpadding
がデフォルトで適用されている
<Container>Hello World</Container>
backgroud-color、height
などを変更したい時は、他のMUIコンポーネントに共通している sx props
を使用すると良い。
<Container sx={{bgcolor: 'cyan', height: '64px'}}>Hello World</Container>
Box
MUIのテンプレートを見ているとめっちゃ見る要素。
div
タグに変換されるが、あえてBox
を使用する理由は sx props
を使用できることにある
せっかくなので、sx
も少し深ぼってみる
sx
スタイルをシュートハンド記法で書くことができる仕組みを提供してくれている。
<Container
sx={{
bgcolor: 'cyan',
boxShadow: 1,
borderRadius: 2,
p: 2,
minWidth: 300,
}}
>Hello World</Container>
使用しているbgcolor
などはCSSのプロパティでは backgroud-color
になるが、これはMUIのショートハンド(省略記法)で、以下のような省略がある。
p: padding
m: margin
py: padding top & bottom
使用可能なプロパティのリストも公式に載っているので、こちらを参考にすると良い
その他、MUIを初めて使ってみて慣れない記法があったので、少しまとめようと思う
spacingプロパティ
margin, padding
などの spacing
プロパティでは px
を使用するのではなく 1, 2 ... と数値型を指定する。
<Typography sx={{m: 1, bgcolor: 'pink'}}>Hello</Typography>
1 = 8px と 8px単位で組み込まれていることに注意が必要。
「めんどくさくね?」と感じるかもしれないが、8pxルールが設けられていることでコンテンツの大きさや余白の秩序をより厳密に保ちやすくなるようにも感じる
hover
便利だと感じたのはhoverを指定できること
通常、style
に指定しても hover
を効かせることはできない
// 以下のホバーは機能しない
<Button style={{background: 'cyan', ':hover': {background: 'gray'}}}>送信</Button>
が、sx
を使用することで hover
を適用できる
<Button sx={{bgcolor: 'cyan', ':hover': {bgcolor: 'gray'}}}>送信</Button>
そして、これは他の擬似要素(::befire, ::after
など)でも適用できる。
例えば、 before, after
擬似要素にスタイルを当てることもできる。
<Box
sx={{
position: 'relative',
p: 2,
my: 2,
"&::before, &::after": {
content: '""',
position: 'absolute',
width: '100%',
height: '2px',
bgcolor: 'black',
},
"&::before": {
top: 0,
},
"&::after": {
bottom: 0,
},
}}
>
<Typography variant="h6" textAlign="center">
Box with Top and Bottom Lines
</Typography>
</Box>
以下のように、擬似要素にスタイルを当てて、線を表現することもできる
ブレイクポイント
ブレイクポイントに合わせたスタイルを適用することもできるのでレスポンシブデザインも簡単に設定できる
// xs: 0px
// sm: 600px
// md: 900px
// lg: 1200px
// XL: 1536px
<Box
sx={{
bgcolor: 'cyan',
width: {
xs: 100,
xl: 1200,
},
}}
>
<Typography variant="h6" textAlign="center">
Box with Top and Bottom Lines
</Typography>
</Box>
また、デフォルトの設定では xs, lg
とかぱっと見、「どのような条件で値を変化させるのか」のルールが分かりにくい。もっと直感的な命名にしたいこともあるだろう。
width: { pc: 100, mobile: 1200}
のように PC, Mobile版 とユースケースを明確にしたい。
そんな時はカスタムテーマを設定し、適用したい範囲を ThemeProvider
でラップすると良い。
import * as React from 'react';
import Box from '@mui/material/Box';
import { createTheme, ThemeProvider } from '@mui/material/styles';
const theme = createTheme({
breakpoints: {
values: {
mobile: 0,
tablet: 640,
laptop: 1024,
desktop: 1280,
},
},
});
export default function CustomBreakpoints() {
return (
<ThemeProvider theme={theme}>
<Box
sx={{
width: {
mobile: 100,
laptop: 300,
},
}}
>
This box has a responsive width
</Box>
</ThemeProvider>
);
}
メモ:
カスタムテーマを各ファイルで呼び出すと冗長なので、theme
ファイルを作成し、App.js
あたりでprovide
してしまうのが綺麗なんじゃないかと思う
// 略
export const theme = createTheme({
breakpoints: {
values: {
mobile: 0,
tablet: 640,
laptop: 1024,
desktop: 1280,
},
},
});
// 略
function App() {
return (
<ThemeProvider theme={theme}>
<AppContextProvider>
// routerとかの定義
</AppContextProvider>
</ThemeProvider>
);
}
Typography
文字を入力する時に使用する
デフォルトで pタグ
として出力されるが、variant props
を使用することでh1タグなどに変換できる
variant
の種類も公式に載っているので良い感じに使い分けたい。
ちなみに variant props
は他のコンポーネント( Buttonコンポーネント とか)にも用意されているので、用途にあったvariant
をチョイスしたい。
<Container sx={{bgcolor: 'cyan', height: '88px'}}>
<Typography variant='h3'>Hello World</Typography>
<Typography variant='subtitle1'>good morning!</Typography>
</Container>
備考
Container, Box, Typography
とMUIの記法についてざっくり分かるとあとはテンプレートを見ると書いている内容がざっくり理解できる...はず。
基本的にはテンプレートをコピペして、必要な部分のみに削ったり、詳細なプロパティを調整するだけで立派なレイアウトを組み立てることができそうです。
まとめ
ここまでみていただきありがとうございます。 m(._.)m
MUIを使う上で頻出のコンポーネントについて軽く触れました。
記事には載せてはいませんが、テンプレートを使った上で感じたことは
- 書き方にルールがあるため、スタイリングに規則性が生まれそう
- 基本テンプレを調整するだけで実装できるのでリードタイムを格段に短縮できそう
などとメリットも感じますが
- デフォルトで存在する padding などを調整したい時は上書きで行う必要がある
- 単位、書き方が特殊なのでキャッチアップにコストがかかる
- アプデがあった時の追随が結構しんどいかも
- MUIのデザインに引っ張られるので、オーバーライドが多いと実装が大変
といったデメリットもあり、全部MUIで書くと後々恨まれそうな気がします。
しかし、カレンダー や chart など普通に実装するとあまりにめんどくさい機能をサクッと実装できる機能を提供していることもあるので、この恩恵は捨てがたい...
実装がしんどい部分だけをMUIにしてみるなどの手段も候補に入れても良さそうですね。