ReactとNext.jsでSVGを使う:完全統合ガイド
ReactとNext.jsアプリケーションでのSVG統合をマスターしましょう。インポート方法、コンポーネントパターン、最適化、モダンWeb開発のベストプラクティスを学べます。

Founder of VectoSolve
Self-taught developer, founder and sole developer of VectoSolve since 2024. He builds the conversion engine and the cutting, embroidery and 3D printing exports.
How this article was made: drafted with AI assistance, then edited and fact-checked before publication. About the author
Key Takeaways
- Reactは4つの主要なSVGインポート方法を提供:画像インポート、インラインSVG、SVGRコンポーネント、動的インポート
- Next.jsのwebpack設定によるSVGRは、開発者体験とランタイム制御の最適なバランスを提供
- TypeScriptプロップス(size、color、className)を持つ再利用可能なアイコンコンポーネントでコードをDRYに保つ
- Framer MotionはSVG要素とネイティブに統合し、スプリングベースのパスとシェイプアニメーションを実現
-
スクリーンリーダーのアクセシビリティのために、SVGアイコンには常に
aria-labelまたはaria-hiddenを追加
モダンReact開発におけるSVG
SVGはモダンなReactアプリケーションに不可欠で、あらゆるスケールでクリスプなグラフィックスを提供します。このガイドでは、ReactとNext.jsプロジェクトでSVGを使用するすべての方法をカバーします。
インポート方法
1. 標準画像インポート
最もシンプルなアプローチ:
import logo from './logo.svg';
function Header() {
return <img src={logo} alt="ロゴ" className="logo" />;
}
メリット:シンプル、馴染みがある
デメリット:スタイリング/操作のアクセスなし
2. インラインSVGコンポーネント
完全な制御:
function Icon() {
return (
<svg viewBox="0 0 24 24" className="icon">
<path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5"/>
</svg>
);
}
メリット:CSS/JSへの完全アクセス
デメリット:冗長、ソースの変更が困難
3. SVGR(Reactコンポーネント)
コンポーネントとしてインポート:
import { ReactComponent as Logo } from './logo.svg';
function Header() {
return <Logo className="logo" fill="currentColor" />;
}
メリット:両方の良いとこ取り
デメリット:設定が必要
4. 動的インポート
コード分割用:
import dynamic from 'next/dynamic';
const DynamicIcon = dynamic(() => import('./icons/chart.svg'));
function Dashboard() {
return <DynamicIcon />;
}
Pro Tip: ほとんどのReactプロジェクトでは、SVGRが推奨アプローチです。SVGファイルをデザインツールで簡単に編集できるよう別々に保ちながら、完全なプロップサポート付きのReactコンポーネントとしてSVGをインポートできます。
SVGR設定
Next.jsセットアップ
// next.config.js
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
use: ['@svgr/webpack'],
});
return config;
},
};
URLフォールバック付き
// next.config.js
module.exports = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/,
issuer: /\.[jt]sx?$/,
use: [
{
loader: '@svgr/webpack',
options: {
svgoConfig: {
plugins: [{
name: 'removeViewBox',
active: false
}]
}
}
},
'url-loader'
],
});
return config;
},
};
A Full Year of Conversions for $49
Starter Annual: 25 conversions every month, $49 for the whole year. That is about $4.08 a month · Cancel anytime
Get the Annual Dealコンポーネントパターン
再利用可能なアイコンコンポーネント
interface IconProps {
name: string;
size?: number;
color?: string;
className?: string;
}
export function Icon({ name, size = 24, color = 'currentColor', className }: IconProps) {
return (
<svg
width={size}
height={size}
fill={color}
className={className}
>
<use href={`/sprites.svg#${name}`} />
</svg>
);
}
// 使用例
<Icon name="search" size={20} color="#333" />
アイコンライブラリコンポーネント
// icons/index.tsx
import { FC, SVGProps } from 'react';
interface IconComponentProps extends SVGProps<SVGSVGElement> {
size?: number;
}
const createIcon = (path: string): FC<IconComponentProps> => {
return function IconComponent({ size = 24, ...props }) {
return (
<svg
viewBox="0 0 24 24"
width={size}
height={size}
fill="currentColor"
{...props}
>
<path d={path} />
</svg>
);
};
};
export const SearchIcon = createIcon('M15.5 14h-.79l-.28-.27...');
export const HomeIcon = createIcon('M10 20v-6h4v6h5v-8h3L12...');
ReactでのSVGスタイリング
CSSスタイリング
/* styles.css */
.icon {
width: 24px;
height: 24px;
fill: currentColor;
transition: fill 0.2s;
}
.icon:hover {
fill: #0066cc;
}
Styled Components
import styled from 'styled-components';
const StyledSvg = styled.svg`
width: ${props => props.size || 24}px;
height: ${props => props.size || 24}px;
fill: ${props => props.color || 'currentColor'};
transition: fill 0.2s;
&:hover {
fill: ${props => props.hoverColor || props.color};
}
`;
Tailwind CSS
<svg
className="w-6 h-6 fill-current text-gray-600 hover:text-blue-500 transition-colors"
viewBox="0 0 24 24"
>
<path d="..."/>
</svg>
「ReactでのベストなSVGワークフローは、デザイナーがクリーンなベクターをエクスポートし、開発者がそれらをファーストクラスのコンポーネントとしてインポートする — 間に手動変換ステップがないワークフローです。」 — Kent C. Dodds、Reactエデュケーター
Reactでのアニメーション
CSSアニメーション
function LoadingSpinner() {
return (
<svg className="animate-spin" viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12" cy="12" r="10"
stroke="currentColor" strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
/>
</svg>
);
}
Framer Motion
import { motion } from 'framer-motion';
function AnimatedIcon() {
return (
<motion.svg
viewBox="0 0 24 24"
initial={{ scale: 0 }}
animate={{ scale: 1 }}
transition={{ type: 'spring' }}
>
<motion.path
d="M12 2L2 22h20L12 2z"
initial={{ pathLength: 0 }}
animate={{ pathLength: 1 }}
/>
</motion.svg>
);
}
Free SVG Tools for Crafters
Design Checker · Color Separator · Mat Preview · Offset Generator · Text to SVG
Check Your SVG Free最適化戦略
ビルド時最適化
// svgo.config.js
module.exports = {
plugins: [
'preset-default',
'removeDimensions',
{ name: 'removeViewBox', active: false },
{ name: 'prefixIds', params: { prefix: 'svg-' } }
]
};
コード分割
// 重いアイコンの遅延読み込み
const ChartIcon = lazy(() => import('./icons/Chart'));
function Dashboard() {
return (
<Suspense fallback={<div className="icon-placeholder" />}>
<ChartIcon />
</Suspense>
);
}
SVGO最適化中にviewBoxを削除しないでください。viewBoxがないと、SVGはレスポンシブにスケーリングする能力を失います。SVGO設定では常にremoveViewBox: falseを設定してください。
Reactでのアクセシビリティ
アクセシブルなアイコンパターン
interface AccessibleIconProps {
label: string;
children: React.ReactNode;
}
function AccessibleIcon({ label, children }: AccessibleIconProps) {
return (
<span role="img" aria-label={label}>
{children}
</span>
);
}
// 使用例
<AccessibleIcon label="検索">
<SearchIcon />
</AccessibleIcon>
アイコンボタン
function IconButton({ icon: Icon, label, onClick }) {
return (
<button
onClick={onClick}
aria-label={label}
className="icon-button"
>
<Icon aria-hidden="true" />
</button>
);
}
VectoSolve統合
ワークフロー
VectoSolveをReactで使用:
- 画像をSVGに変換
- 最適化された出力をダウンロード
- Reactプロジェクトにインポート
- 上記の好みの方法を使用
最適化ファイルのメリット
VectoSolveのSVGは:
- Web使用に最適化
- SVGRインポート対応
- クリーンなパスデータ
- スタイリングが簡単
A Full Year of Conversions for $49
Starter Annual: 25 conversions every month, $49 for the whole year. That is about $4.08 a month · Cancel anytime
Get the Annual Dealまとめ
ReactにはSVGを操作する複数の方法があり、それぞれにトレードオフがあります。ニーズに合ったアプローチを選びましょう:基本的な使用にはシンプルな画像インポート、完全な制御にはSVGR、アイコンシステムにはコンポーネントパターン。最良の結果を得るには、VectoSolveのクリーンで最適化されたSVGから始めましょう。
| SVGインポート方法 | ランタイム制御 | バンドルへの影響 | 最適な用途 |
|---|---|---|---|
| <img src> インポート | なし | 別のHTTPリクエスト | 静的な装飾画像 |
| インラインJSX SVG | 完全(プロップス、イベント、CSS) | コンポーネントサイズ増加 | インタラクティブアイコン、アニメーション |
| SVGRコンポーネント | 完全(型付きプロップス、ツリーシェイキング) | コンポーネントごとのチャンク | アイコンライブラリ、デザインシステム |
| 動的インポート | 完全(読み込み後) | コード分割、遅延読み込み | ファーストビュー以下または条件付きSVG |
参考資料・関連記事
- MDN Web Docs: SVG in HTML — JSXへのSVG埋め込みとSVG-DOMインタラクションの理解のための参照
- web.dev: Code Splitting — 最適なバンドルサイズのための遅延読み込みと動的インポートに関するGoogleのガイド
- CSS-Tricks: SVG in React — ReactとNext.jsプロジェクトでSVGコンポーネントを使用するための実用パターン
- Smashing Magazine: React Components — 再利用可能でアクセシブルなSVGコンポーネントライブラリ構築のベストプラクティス