material-iconsをcssだけで指定したい場合の話

# 概要
この記事では、CSSだけを駆使して、Material-UIのアイコン(詳しくは下記の[material-iconsとは？](#material-iconsとは？)をご覧ください。)を設定する方法をご紹介します。

例えば、下記の場合に使えます。
- javascriptのフレームワークを使わずに素早くMaterial-UIのアイコンを追加したい場合
- CSSの`::before`, `::after`などの疑似要素でMaterial-UIのアイコンを設定した場合

#### 使っているバージョン（2023/03/25 執筆時点）
　React: v18.2.0
　@mui/material: v5.14.4
　@mui/icons-material: v5.15.11

## Material-UI(MUI)とは？
まず、Material-UIについて簡単に説明します。

Material-UI（現在はMUIとして知られています。この記事では、MUIという略称で参照します。）は、Reactコンポーネントを使用して構築された人気のあるフロントエンドフレームワークであり、Googleのマテリアルデザインガイドラインに基づいています。このライブラリは、開発者が美しい、一貫性のあるUIを迅速に構築できるように設計されており、幅広い準備済みのコンポーネントを提供しています。これらには、ボタン、カード、ダイアログ、アイコンなどの基本的なUI要素から、データテーブル、ナビゲーションバー、スライダーなどのより複雑なコンポーネントまでが含まれます。

MUIの最大の利点の一つは、そのカスタマイズ性です。デフォルトのテーマを簡単にカスタマイズできるため、ブランドのカラースキーム、タイポグラフィ、その他のデザイン要素に合わせてアプリケーションの見た目を調整できます。さらに、CSS-in-JS技術を使用してスタイリングすることが推奨されており、これによりスタイルの定義と管理が容易になります。

### MUIの例：
以下は、MUIを使用して簡単なボタンコンポーネントを作成する例です。

まず、プロジェクトにMUIをインストールします。
```bash
npm install @mui/material @emotion/react @emotion/styled
```

次に、Button コンポーネントをインポートして使用します。
```jsx
import React from 'react';
import Button from '@mui/material/Button';

function App() {
  return (
    <div>
      {/* カラーテーマが "primary" のcontainedボタン */}
      <Button variant="contained" color="primary">CONTAINED</Button>
    </div>
  );
}

export default App;
```

#### 画面表示例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726546/7ceae643-67cd-74aa-77af-739baeec52b4.png)

上記の例のように、MUIを使用することで、コードの量を最小限に抑えつつ、直感的で一貫性のあるインターフェースを迅速に構築できます。

詳しくはmuiのホームページをご覧ください。
https://mui.com/material-ui/getting-started/

## material-iconsとは？
material-iconsはMUIと同じくGoogleのマテリアルデザイン原則に基づいているアイコンセットです。material-iconsは、MUIのコンポーネントとシームレスに組み合わせることができ、デザインと機能性の両方を重視したアプリケーションを効率的に構築できます。

#### material-iconsの例
material-iconsを使うためには@mui/icons-materialというライブラリーをインストールが必要です。

```bash
npm install @mui/icons-material
```

次に、必要なアイコンをインポートして、Reactコンポーネント内で使用します。例えば、ホームアイコンを追加する場合は以下のようにします。

```jsx
import React from 'react';
import Button from '@mui/material/Button';
import HomeIcon from '@mui/icons-material/Home';

function HomeButton() {
  return (
    <Button>
      <HomeIcon />
      Home
    </Button>
  );
}

export default HomeButton;
```

#### 画面表示例：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726546/cb23ebd6-3935-acd9-df0e-8542b559e2a0.png)


上記の例のように、アイコンのコンポーネントをimportして、描画するだけで簡単に美しいアイコンが無料で使えるようになります。

下記のurlからお好きなアイコンを探してみてください。
https://mui.com/material-ui/material-icons/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726546/a811012f-cf47-3fd8-08d9-4360624f68c7.png)

# CSSのみでアイコンを指定する方法
簡単に説明しますと、CSSのurl()関数を使って、material-iconsを指定するだけです。
### CSSのurl()関数とは？
CSSの`url()`関数は、外部リソース（例えば、画像、フォントファイル、その他のメディアファイル）を参照するために使用されます。
```css
/* 背景画像の設定例 */
.element {
  background-image: url('images/background.jpg');
}
```

### material-iconsのURL
material-iconsをinstallすると、node_modulesフォルダーに全てのアイコンを参照できるようになります。
node_modulesフォルダは、プロジェクトのルートディレクトリに位置しています。

例えば、下記のコマンドを叩いて、フォルダーのAlarm.jsの中身を見てみましょう。
[ProjectRoot]を適切なパスに置き換えてください。
```bash
cat [ProjectRoot]/node_modules/@mui/icons-material/Alarm.js
```

ターミナルには下記の内容が表示されます。
```js
1  "use strict";
2  "use client";
3  
4  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
5  Object.defineProperty(exports, "__esModule", {
6    value: true
7  });
8  exports.default = void 0;
9  var _createSvgIcon = _interopRequireDefault(require("./utils/createSvgIcon"));
10 var _jsxRuntime = require("react/jsx-runtime");
11 var _default = exports.default = (0, _createSvgIcon.default)( /*#__PURE__*/(0, _jsxRuntime.jsx)("path", {
12   d: "m22 5.72-4.6-3.86-1.29 1.53 4.6 3.86zM7.88 3.39 6.6 1.86 2 5.71l1.29 1.53zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9m0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7"
13 }), 'Alarm');
```

上記の13行目では、Alarmアイコンを`path`要素の`d属性`(`("path", {d: m22 5.72...7-7 7}), 'Alarm')`)にmから始まる)SVGパスデータで定義していることがわかります。

このSVGパスデータを下記のCSSで指定することで、`::before`疑似要素でMuiのアイコンを表示させることができます。

```css
.element::before {
  display: inline-block; /* アイコンの大きさを調整のためにinline-blockなどを設定 */
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' style='fill: %233170C1;' viewBox='0 0 24 24' %3E%3Cpath d='m22 5.72-4.6-3.86-1.29 1.53 4.6 3.86zM7.88 3.39 6.6 1.86 2 5.71l1.29 1.53zM12.5 8H11v6l4.75 2.85.75-1.23-4-2.37zM12 4c-4.97 0-9 4.03-9 9s4.02 9 9 9c4.97 0 9-4.03 9-9s-4.03-9-9-9m0 16c-3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7'%3E%3C/path%3E%3C/svg%3E"); /* アイコンのURLを指定 */
  width: 24px; /* アイコンの大きさを調整 */
  vertical-align: middle; /* アイコンの垂直位置を調整 */
}
```
#### cssの解説：
- アイコンを他のMUIのアイコンにしたい場合:
上記の`url()`内の`m22 5.72...省略...7-7 7`を対象アイコンのSVGパスに置き換える（SVGパスはnode_modulesフォルダーから対象アイコンを探して直接コピーしてください）
- 色を変更したい場合:
url()内のfill: %233170C1;を白色(`#ffffff`)に変更したい場合は`%23ffffff`に変更する。（urlにencodeされるため、`#XXXXXX`ではなく`%23XXXXXXで`色を指定する）
- アイコンのサイズを調整したい場合:
widthでアイコンのサイズを調整できるが、数値を変えても反映されない場合は、displayの設定を変えてみてください。

# 結論
CSSのみを使って、MUIのアイコンを指定する方法は以外と簡単ですね～
手を動かしてやってみましょう～