Material UI の使い方
React を使用してガリガリに画面を作っていくのであれば、より使いやすいデザインや UI / UX を追求していきたいところでしょう。 しかしながら、どんなデザインが使いやすいデザインと言えるのかは難しい問題です。 そういった場合は、Material Design の採用を検討してみるのも良いかもしれません。
Material Design とは?
Material Design は、Google のデザイナーと開発者によって構築およびサポートされているデザインシステムです。 デザインシステムというのは、どういったデザインにすると良いのかといったようなことがまとめられたデザインのガイドライン(仕様書)のようなものだと思ってもらって良いと思います。 例えば、ボタンを1つデザインするだけでも、大きさはどれくらいが良いのかとか、色は何色にすれば良いのかとか、間隔はどれくらいにすれば良いのかとか、考えなければならないことがたくさんあると思います。 そういった細かなデザインに関する仕様が体系的にまとめられているものになります。 デザインシステムを使用して画面を作成することで、一貫性のある UI / UX を実現することができます。 Material Design は Google 製ですので、Google のサービスに使用されていることが多いと思います。 最も身近でわかりやすい例としては、スマホの Andorid の UI を想像してもらうのが良いのではないでしょうか。
Material UI とは?
Material Design はデザインシステム、つまりデザインのガイドライン(仕様書)ですので、 Material Design を使用して開発を行うには、その Material Design で定められている細かな仕様に従って自分で実装する必要があります。 しかしながら、その細かな仕様に従って自分で一から作っていくのはかなり大変です。
Material UI は Material Design を React 上で簡単に使用できるようにした React コンポーネントのライブラリです。 Material UI を使用すると、Material Design で定められている細かな仕様を意識することなく、キレイで使いやすい画面を簡単に作ることができるようになります。
Material UI のインストール
さっそくですがインストールしていきましょう。
Material UI をインストールするには、npm を使用します。 npm の使い方がわからないという方は、「Node.js と npm の使い方(その1:概要)」を参考にしてください。
Material UI の本体をインストール
Material UI は、デフォルトのスタイリングエンジンとして Emotion というライブラリが使用されているため、 Material UI 本体のパッケージ「@mui/material」と、Emotion 用のパッケージ「@emotion/react」「@emotion/styled」の合計3つのパッケージが必要になります。
npm install --save-dev @mui/material @emotion/react @emotion/styled
Roboto フォントをインストール
Material UI ではデフォルトのフォントとして Roboto フォントが使用されています。 Roboto は Android のデフォルトフォントとしても有名です。 Roboto を使用しない場合はインストール不要ですが、使用する場合はインストールしておきましょう。 Roboto をインストールするには、Web フォント(CDN)を使用する方法と、npm を使用する方法の2つがあります。
Web フォント(CDN)を使用する
Web フォントを使用するには、使用したいフォントファイルを HTML の link
タグで読み込みます。
下記の例では Google Fonts の CDN を使用していますが、このファイルをダウンロードして、自分で配信することもできます。
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap">
npm を使用する
npm を使用する場合は、「@fontsource/roboto」パッケージが必要になります。
npm install --save-dev @fontsource/roboto
そして、Roboto を使用するファイルで Roboto 用の CSS ファイルを import
する必要があります。
import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css';
なお、webpack でビルドした際に、CSS ファイルの読み込みでエラーが発生する場合は、webpack で CSS を読み込めるように変更する必要があるので注意してください。 webpack で CSS を読み込むためには「style-loader」と「css-loader」の2つのパッケージが必要になります。
npm install --save-dev style-loader css-loader
module.exports = { module: { rules: [ // webpack で .css ファイルを読み込めるようにする // ※ style-loader を先に書く必要があるので注意 { test: /\.css$/i, use: ['style-loader', 'css-loader'], }, ], }, };
アイコン表示用のフォントをインストール
Material UI ではアイコン表示用のフォントとして Material Icons フォントが使用されています。 Material Icons はアイコン表示用の SVG データをフォントとして登録してある特別なフォントで、Google 製の Font Awesome のようなものだと思っていただければ良いかと思います。
Material UI でアイコンを表示する方法は、大きく分けて3種類存在し、それぞれ必要な作業が異なりますので注意してください。 なお、アイコンを使用しない場合は、これらの作業は必要ありません。
Material SVG icons を使用する場合
Material SVG icons を使用する場合は、「@mui/icons-material」パッケージが必要になります。
npm install --save-dev @mui/icons-material
SvgIcon を使用する場合
SvgIcon を使用する場合は、 アイコン表示用のフォントをインストールする作業は必要ありませんが、 もし webpack を使用していて、SVG を別のファイルから読み込んで使用したい場合は、「@svgr/webpack」パッケージが必要になります。
npm install --save-dev @svgr/webpack
module.exports = { module: { rules: [ // webpack で .svg ファイルを読み込めるようにする { test: /\.svg$/, use: ['@svgr/webpack'], }, ], }, };
Icon (Font icons) を使用する場合
Icon (Font icons) を使用する場合は、Material Icons フォントを Web フォントとして読み込む必要があります。
Web フォントを使用するには、使用したいフォントファイルを HTML の link
タグで読み込みます。
下記の例では Google Fonts の CDN を使用していますが、このファイルをダウンロードして、自分で配信することもできます。
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
基本的な使い方
インストールできたら実際に使用してみましょう。
Material UI は React のコンポーネントとして使用することができます。
使用したい Material UI のコンポーネントを import
で読み込んで、そのコンポーネントを表示したい場所に JSX でタグとして記述していきます。
React の使い方がわからないという方は、「React の使い方」を参考にしてください。
Material UI で使用できるコンポーネントはかなり数が多いので、 詳しい説明は公式のドキュメントを見てもらった方が良いかと思います。 この記事では、ボタンを表示するだけの簡単な例を紹介します。
ボタンを表示する
Material UI でボタンを表示するには、Button コンポーネントを使用します。
ボタンのデザインの種類は variant
属性で指定できます。
デフォルトの variant
は text
になります。
// import for React import React from 'react'; import ReactDOM from 'react-dom/client'; // import for Roboto フォント // ※ Roboto を使用しない場合や、Web フォント(CDN)を使用している場合は不要 import '@fontsource/roboto/300.css'; import '@fontsource/roboto/400.css'; import '@fontsource/roboto/500.css'; import '@fontsource/roboto/700.css'; // import for Material UI import Button from '@mui/material/Button'; // 「MySection」コンポーネント function MySection() { return ( <section> <h1>This is a h1</h1> {/* これは普通のボタン */} <button>I'm a button</button> {/* 下記の3つは Material UI のボタン */} <Button variant="text">Text</Button> <Button variant="contained">Contained</Button> <Button variant="outlined">Outlined</Button> </section> ); } // React を実行 // HTML の id="app" の位置に「MySection」コンポーネントの内容を描画する const root = ReactDOM.createRoot(document.getElementById('app')); root.render(<MySection />);
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>My React App</title> <!-- Roboto フォントの読み込み(未使用の場合や、npm でインストールしている場合は不要) --> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;600;700&display=swap"> <!-- Material Icon フォントの読み込み(Icon (Font icons) を未使用の場合は不要) --> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <!-- JavaScript を読み込み(webpack で変換したファイル) --> <script defer src="./dist/main.js"></script> </head> <body> <p>This paragraph is a part of HTML.</p> <!-- この位置に描画される --> <div id="app"></div> <p>This paragraph is also a part of HTML.</p> </body> </html>
デザインを変更する
デフォルトのデザインでも十分にキレイではあるのですが、実際に使用する際には細かなデザインの変更等が必要になるかと思います。 例えば、サイトのブランドイメージに合わせて、背景や文字の色を変更したりする必要が出てくるでしょう。
テーマを使用する
コンポーネントのデザインを1つずつ個別に変えても良いのですが、それだと全体的に統一感が無くなってしまいますし、メンテナンスも大変になってしまいます。 テーマを使用すると、複数のコンポーネントのデザインをまとめて変更することができます。
テーマを使用するためには、まず createTheme()
でテーマオブジェクトを作成する必要があります。
次に、テーマを適用したい範囲を ThemeProvider
コンポーネントで囲みます。
そして、ThemeProvider
コンポーネントの theme
属性で、作成したテーマオブジェクトを指定します。
すると、ThemeProvider
で囲んだ範囲だけデザインを変更することができます。
また、ThemeProvider
コンポーネントはネストすることもできますので、複数のテーマを同時に適用させることも可能です。
テーマで設定できる項目やデフォルトの値は、公式のドキュメントを参照してください。
// import for React import React from 'react'; import ReactDOM from 'react-dom/client'; // import for Material UI import Button from '@mui/material/Button'; import { ThemeProvider, createTheme } from '@mui/material/styles'; // テーマを作成 const theme = createTheme({ // フォント // ※ デフォルトは ""Roboto", "Helvetica", "Arial", sans-serif" になっているが、 // Roboto フォントを使用する場合は、Roboto をインストールする必要があるので注意 typography: { fontFamily: 'Meiryo, "MS PGothic", sans-serif', }, // カラーパレット palette: { primary: { main: '#666', // light: will be calculated from palette.primary.main, // dark: will be calculated from palette.primary.main, // contrastText: will be calculated to contrast with palette.primary.main }, }, }); // 「MySection」コンポーネント function MySection() { return ( <section> <h1>This is a h1</h1> {/* これは普通のボタン */} <button>I'm a button</button> {/* 作成したテーマを使用 */} <ThemeProvider theme={theme}> {/* 下記の3つは Material UI のボタン */} <Button variant="text">Text</Button> <Button variant="contained">Contained</Button> <Button variant="outlined">Outlined</Button> </ThemeProvider> </section> ); } // React を実行 // HTML の id="app" の位置に「MySection」コンポーネントの内容を描画する const root = ReactDOM.createRoot(document.getElementById('app')); root.render(<MySection />);
sx 属性を使用する
Material UI の全てのコンポーネントは、sx 属性でスタイルを変更することができます。 テーマでは対応しきれないような局所的な変更を行う際に使用すると良いでしょう。
// import for React import React from 'react'; import ReactDOM from 'react-dom/client'; // import for Material UI import Button from '@mui/material/Button'; // 「MySection」コンポーネント function MySection() { return ( <section> <h1>This is a h1</h1> {/* これは普通のボタン */} <button>I'm a button</button> {/* 下記の3つは Material UI のボタン */} <Button variant="text">Text</Button> <Button variant="contained" sx={{ background:"#090" }}>Contained</Button> <Button variant="outlined">Outlined</Button> </section> ); } // React を実行 // HTML の id="app" の位置に「MySection」コンポーネントの内容を描画する const root = ReactDOM.createRoot(document.getElementById('app')); root.render(<MySection />);
コンポーネントを継承する
styled()
を使用すると、既存のコンポーネントを継承したコンポーネントを作ることができます。
作成したコンポーネントをアプリケーション全体で再利用したい場合には便利かもしれません。
// import for React import React from 'react'; import ReactDOM from 'react-dom/client'; // import for Material UI import Button from '@mui/material/Button'; import { styled } from '@mui/material/styles'; // Button を継承したボタンを作成 const CustomButton = styled(Button)({ color: 'darkslategray', backgroundColor: 'aliceblue', padding: 8, borderRadius: 4, }); // 「MySection」コンポーネント function MySection() { return ( <section> <h1>This is a h1</h1> {/* これは普通のボタン */} <button>I'm a button</button> {/* これは styled() で作ったボタン */} <CustomButton>Custom</CustomButton> </section> ); } // React を実行 // HTML の id="app" の位置に「MySection」コンポーネントの内容を描画する const root = ReactDOM.createRoot(document.getElementById('app')); root.render(<MySection />);
参考サイト
- Googleが推奨する「マテリアルデザイン」とは?5つの特徴と、メリット・デメリット・作り方について解説 | Tayori Blog
- Material Design
- 【React】Material UIの使い方【導入から解説】 | RalaCode
- Material UI: React components based on Material Design
- Installation - Material UI
- Emotion – Introduction
- React Icon Component - Material UI
- Supported components - Material UI
- React Button component - Material UI
- How to customize - Material UI
- Theming - Material UI
- Default theme viewer - Material UI
- The sx prop - MUI System
- styled() - MUI System