Material UI の使い方

React を使用してガリガリに画面を作っていくのであれば、より使いやすいデザインや UI / UX を追求していきたいところでしょう。 しかしながら、どんなデザインが使いやすいデザインと言えるのかは難しい問題です。 そういった場合は、Material Design の採用を検討してみるのも良いかもしれません。

Material Design とは?

Material Design は、Google のデザイナーと開発者によって構築およびサポートされているデザインシステムです。 デザインシステムというのは、どういったデザインにすると良いのかといったようなことがまとめられたデザインのガイドライン(仕様書)のようなものだと思ってもらって良いと思います。 例えば、ボタンを1つデザインするだけでも、大きさはどれくらいが良いのかとか、色は何色にすれば良いのかとか、間隔はどれくらいにすれば良いのかとか、考えなければならないことがたくさんあると思います。 そういった細かなデザインに関する仕様が体系的にまとめられているものになります。 デザインシステムを使用して画面を作成することで、一貫性のある UI / UX を実現することができます。 Material Design は Google 製ですので、Google のサービスに使用されていることが多いと思います。 最も身近でわかりやすい例としては、スマホの Andorid の UI を想像してもらうのが良いのではないでしょうか。

Material UI とは?

material_ui_thumb.png

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つのパッケージが必要になります。

例:「@mui/material」「@emotion/react」「@emotion/styled」パッケージをインストールする場合
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 を使用していますが、このファイルをダウンロードして、自分で配信することもできます。

HTML
<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 する必要があります。

JavaScript(ES Modules)
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
webpack.config.js
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
webpack.config.js
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 を使用していますが、このファイルをダウンロードして、自分で配信することもできます。

HTML
<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 属性で指定できます。 デフォルトの varianttext になります。

JavaScript(ES Modules)
// 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 />);
HTML
<!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>
default.png

デザインを変更する

デフォルトのデザインでも十分にキレイではあるのですが、実際に使用する際には細かなデザインの変更等が必要になるかと思います。 例えば、サイトのブランドイメージに合わせて、背景や文字の色を変更したりする必要が出てくるでしょう。

テーマを使用する

コンポーネントのデザインを1つずつ個別に変えても良いのですが、それだと全体的に統一感が無くなってしまいますし、メンテナンスも大変になってしまいます。 テーマを使用すると、複数のコンポーネントのデザインをまとめて変更することができます。

テーマを使用するためには、まず createTheme() でテーマオブジェクトを作成する必要があります。 次に、テーマを適用したい範囲を ThemeProvider コンポーネントで囲みます。 そして、ThemeProvider コンポーネントの theme 属性で、作成したテーマオブジェクトを指定します。 すると、ThemeProvider で囲んだ範囲だけデザインを変更することができます。 また、ThemeProvider コンポーネントはネストすることもできますので、複数のテーマを同時に適用させることも可能です。 テーマで設定できる項目やデフォルトの値は、公式のドキュメントを参照してください。

JavaScript(ES Modules)
// 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 />);
theme.png

sx 属性を使用する

Material UI の全てのコンポーネントは、sx 属性でスタイルを変更することができます。 テーマでは対応しきれないような局所的な変更を行う際に使用すると良いでしょう。

JavaScript(ES Modules)
// 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 />);
sx.png

コンポーネントを継承する

styled() を使用すると、既存のコンポーネントを継承したコンポーネントを作ることができます。 作成したコンポーネントをアプリケーション全体で再利用したい場合には便利かもしれません。

JavaScript(ES Modules)
// 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 />);
styled.png

参考サイト

関連記事

最近では CSS フレームワークとして Tailwind CSS を使用して開発されている方も多いようです。そこで Tailwind CSS の使い方についてまとめてみます。誰かのお役に立てれば幸いです。Tailwind CSS とは?Tailwind CSS は、オープンソースの CSS フレームワークです。Boot ...
最近では JavaScript のライブラリとして React を使用して開発されている方も多いのではないでしょうか。そこで React の使い方についてまとめてみます。いまさら感がスゴイですが、誰かのお役に立てれば幸いです。React とは?React は、UI(ユーザインターフェース)をコンポーネントと呼ばれる部品 ...
最近の Web の開発では、webpack を使用することはもはや当たり前のような状況です。そこで改めてその使用方法をまとめてみたいと思います。今更かもしれませんが、誰かの参考になれば幸いです。webpack とは?近年の Web 開発では、サーバーサイド(PHP など)ではなく、クライアントサイド(JavaScrip ...
JavaScript は文法的にかなりフレキシブルな言語であり、コードが汚くなりがちです。キレイで読みやすいコードを保つために、JavaScript にも静的解析ツールを導入しましょう。ESLint とは?ESLint は、JavaScript の静的解析ツールです。JavaScript コードを実行する前に(つまり静 ...
最近の Web 界隈では、UX を高めるために、UI を JavaScript でガリガリ実装するというのが普通になってます。フロントエンドエンジニアなんていう職種が生まれるほど、この界隈は活発です。そこでフロントエンド開発でほぼ必須となるであろう Node.js と npm について少しまとめてみます。今更感がすごい ...

記事検索

最新記事

人気記事

RSSフィード

フィードバック

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

匿名でフィードバックする
匿名でフィードバックする

要望などあれば、お気軽にどーぞ。 不具合やバグを発見した場合も、連絡をいただけると助かります。

なお、このフォームから入力された内容について、管理者から返信はできませんので注意してください。 もし、管理者からの返信が必要であれば、X(旧 Twitter) もしくは、お問い合わせより、お願いします。

  • フィードバックの送信が完了しました。