babel-plugin-inline-react-svgというプラグインを利用することでSVGをコンポーネントのように扱えます。
今回はbabel-plugin-inline-react-svgをNext.jsのアプリケーションで利用する方法について紹介します。
検証環境はnext 12.1.4
、react 18.0.0
です。
目次
セットアップ手順
パッケージのインストール
$ yarn add -D babel-plugin-inline-react-svg
.babelの作成と設定追加
babel-plugin-inline-react-svgのREADMEを参考に、.babelrc
の設定をします。
またNext.jsの公式ドキュメントのCustomizing Babel Configにも書いてある通り、next/babel
のプリセットもあわせて追加します。
.babelrc
{
"presets": [ "next/babel" ],
"plugins": [ "inline-react-svg" ]
}
下準備: SVGのダウンロード
今回はGoogle FontsにあるSVGをサンプルとして利用します。
利用方法
SVGの呼び出し方法
SVGを呼び出すサンプルコードは以下の通りです。
コードをみて分かる通り、babel-plugin-inline-react-svgを利用すると通常のコンポーネントのようにSVGもPropsでプロパティを制御できたりCSSを適用できたりします。
src/components/Example.tsx
import { FC } from "react";
import HomeIcon from "../../public/images/home.svg";
import FilledHomeIcon from "../../public/images/filledHome.svg";
import styles from "./Example.module.css";
export const Example: FC = () => {
return (
<>
<HomeIcon width={24} height={24} />
<HomeIcon className={styles.icon} />
<HomeIcon height={48} width={48} fill={"red"} />
<HomeIcon
height={48}
width={48}
fill={"red"}
stroke={"red"}
strokeWidth={2}
/>
<FilledHomeIcon height={48} width={48} fill={"red"} />
</>
);
};
src/components/Example.module.css
.icon {
width: 24px;
height: 24px;
}
PropsでSVGを指定する方法
PropsでSVGを指定するサンプルコードは以下の通りです。
src/components/Example.tsx
import { FC } from "react";
import { Button } from "./shared/Button";
import FilledHomeIcon from "../../public/images/filledHome.svg";
import FilledSettingsIcon from "../../public/images/filledSettings.svg";
import styles from "./Example.module.css";
export const Example: FC = () => {
return (
<>
<Button label={"ホーム"} Icon={FilledHomeIcon} />
<br />
<Button label={"設定"} Icon={FilledSettingsIcon} />
</>
);
};
src/components/shared/Button.tsx
import React, { FC } from "react";
import styles from "./Button.module.css";
type Props = {
label: string;
Icon?: FC<{width: number, height: number, className: string}>
};
export const Button: FC<Props> = ({
label,
Icon,
}) => {
return (
<button
className={styles.button}
>
{Icon ? <Icon width={20} height={20} className={styles.icon} /> : null }
{label}
</button>
);
};
src/components/shared/Button.csss
.button {
font-size: 15px;
height: 50px;
min-width: 100px; /* labelの文字列がボタンからはみ出さないようにするため、横幅を確保しつつ可変長にする */
padding: 0 25px;
color: white;
font-weight: bold;
border-radius: 10px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
background: darkblue;
}
.icon {
fill: #fff;
margin-right: 5px;
}
覚えておくと良いTips
SVGのサイズがうまく変更できない場合
width
とheight
がSVGファイルの<svg>
タグ内に記述されていると、コンポーネントからのサイズ指定がうまく機能しない場合があります。
サイズ指定が機能しない具体例は以下の通りです。
src/components/Example.tsx
import { FC } from "react";
import HomeIcon from "../../public/images/home.svg"
export const Example: FC = () => <HomeIcon width={24} height={24} />;
呼び出したSVGの詳細は以下の通りです。
home.svg
<svg xmlns="http://www.w3.org/2000/svg" height="48" width="48"><path d="M11 39h7.5V26.5h11V39H37V19.5L24 9.75 11 19.5Zm0 3q-1.25 0-2.125-.875T8 39V19.5q0-.7.325-1.35.325-.65.875-1.05l13-9.75q.4-.3.85-.45.45-.15.95-.15.5 0 .95.15.45.15.85.45l13 9.75q.55.4.875 1.05.325.65.325 1.35V39q0 1.25-.875 2.125T37 42H26.5V29.5h-5V42Zm13-17.65Z"/></svg>
結果は以下の通りです。
サイズ指定がうまくいかない場合は<svg>
タグ内のwidth
とheight
の定義を削除し、代わりにviewBox
を追加します。
たとえば以下のように修正します。
- <svg xmlns="http://www.w3.org/2000/svg" height="48" width="48">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48">
上記のようにするとサイズ指定がうまくいきます。
相対パスでSVGファイルを読み込む方法
babel-plugin-module-resolverを追加すると相対パスでSVGファイルが利用できます。
$ yarn add -D babel-plugin-module-resolver
当該プラグインを利用するとパスのrootやaliasの設定ができます。今回はrootの設定のみ行います。
.babelrc
{
"presets": [ "next/babel" ],
"plugins": [
+ ["module-resolver", { "root": ["."] }],
"inline-react-svg"
]
}
上記の設定完了後、SVGファイルは以下のように読み込めます。
- import HomeIcon from "../../public/images/home.svg"
+ import HomeIcon from "public/images/home.svg"
さいごに
Next.jsを導入していないReact環境でSVGを利用する方法についてはReact環境で手軽にSVGを表示する方法で紹介しています。
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!