はじめに
Webアプリを作っていて、「アイコンをどこから持ってこよう?」と手が止まった経験はありませんか?
無料のアイコンサイトを巡っては、サイズ感やテイストがバラバラなSVGを寄せ集めてしまい、気づけばUIに統一感がなくなっている——アイコン選びは、意外とデザインの落とし穴になりがちです。かといって、有料のアイコンセットを契約するほどでもない。そんなときに頼りになるのが、Tailwind CSSの開発元であるTailwind Labsが手がけるHeroiconsです。
デザインの一貫性が保証された高品質なアイコンを、MITライセンスで無料・商用利用OK。しかもReactやVueならコンポーネントとして1行でインポートできます。この記事では、Heroiconsの特徴からフレームワーク別の使い方、実践的なユースケースまでを解説します。
Heroiconsとは
Heroiconsは、Tailwind Labsがデザイン・メンテナンスしているハンドクラフトのSVGアイコンライブラリです。300種類以上のアイコンがそれぞれ複数のスタイルで提供されており、GitHubスターは23,000を超える定番ライブラリとなっています。
Tailwind CSSと同じチームが作っているだけあって、Tailwindのユーティリティクラスとの相性は抜群です。もちろんTailwindを使っていないプロジェクトでも、素のSVGとしてそのまま利用できます。
主な特徴
- 4つのスタイルバリエーション - 同じアイコンが「24px outline」「24px solid」「20px solid(mini)」「16px solid(micro)」の4スタイルで提供され、用途に応じて使い分けられます
- React / Vue公式サポート -
@heroicons/reactと@heroicons/vueが公式提供されており、アイコンをコンポーネントとしてインポートするだけで使えます - currentColor対応 - アイコンの色はCSSの
color(テキスト色)をそのまま継承するため、text-blue-500のようなクラス1つで色を変更できます - MITライセンス - 個人・商用を問わず無料で利用可能。クレジット表記も不要です
スタイルの使い分け
| スタイル | サイズ | 主な用途 |
|---|---|---|
| Outline | 24x24 | ナビゲーション、大きめのUI要素 |
| Solid | 24x24 | 選択状態の表現、強調したい場面 |
| Mini | 20x20 | ボタン内、フォーム、密度の高いUI |
| Micro | 16x16 | テーブル、バッジ、極小スペース |
「未選択はoutline、選択中はsolid」のように切り替えると、状態変化が直感的に伝わるUIを作れます。
インストール
Reactプロジェクトの場合は次のコマンドでインストールします。
# npm
npm install @heroicons/react
# yarn
yarn add @heroicons/react
# pnpm
pnpm add @heroicons/react
Vueプロジェクトの場合はこちらです。
npm install @heroicons/vue
フレームワークを使わない場合はインストール不要です。公式サイト(heroicons.com)でアイコンを検索し、SVGコードをコピーしてHTMLに貼り付けるだけで使えます。
基本的な使い方
Reactでの使い方
アイコンはスタイルごとのパスから個別にインポートします。名前は「ケバブケースのアイコン名をパスカルケースにしてIconを付けた形」です(例: arrow-down → ArrowDownIcon)。
import { BeakerIcon } from '@heroicons/react/24/outline';
export default function Example() {
return (
<button className="flex items-center gap-2 rounded bg-indigo-600 px-4 py-2 text-white">
<BeakerIcon className="size-6" />
実験を開始
</button>
);
}
インポートパスでスタイルを切り替えます。
import { CheckCircleIcon } from '@heroicons/react/24/outline'; // 24px アウトライン
import { CheckCircleIcon } from '@heroicons/react/24/solid'; // 24px ソリッド
import { CheckCircleIcon } from '@heroicons/react/20/solid'; // 20px ミニ
import { CheckCircleIcon } from '@heroicons/react/16/solid'; // 16px マイクロ
色はテキスト色を継承するため、Tailwindならtext-*クラスを付けるだけです。
<CheckCircleIcon className="size-6 text-green-500" />
Vueでの使い方
Vue版もReact版とまったく同じ命名規則です。
<script setup>
import { BeakerIcon } from '@heroicons/vue/24/outline';
</script>
<template>
<button class="flex items-center gap-2 rounded bg-indigo-600 px-4 py-2 text-white">
<BeakerIcon class="size-6" />
実験を開始
</button>
</template>
素のHTMLでの使い方
公式サイトからコピーしたSVGをそのまま埋め込みます。stroke="currentColor"(outline)やfill="currentColor"(solid)が指定されているため、親要素のテキスト色がアイコンに反映されます。
<span style="color: #4f46e5;">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" width="24" height="24">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9.75 3.104v5.714a2.25 2.25 0 0 1-.659 1.591L5 14.5M9.75 3.104c-.251.023-.501.05-.75.082m.75-.082a24.301 24.301 0 0 1 4.5 0m0 0v5.714c0 .597.237 1.17.659 1.591L19.8 15.3M14.25 3.104c.251.023.501.05.75.082M19.8 15.3l-1.57.393A9.065 9.065 0 0 1 12 15a9.065 9.065 0 0 0-6.23-.693L5 14.5m14.8.8 1.402 1.402c1.232 1.232.65 3.318-1.067 3.611A48.309 48.309 0 0 1 12 21c-2.773 0-5.491-.235-8.135-.687-1.718-.293-2.3-2.379-1.067-3.61L5 14.5" />
</svg>
</span>
実践的なユースケース
ナビゲーションメニュー(選択状態でスタイルを切り替え)
サイドバーで「選択中はsolid、未選択はoutline」を切り替える定番パターンです。
import { HomeIcon as HomeOutline, CogIcon as CogOutline } from '@heroicons/react/24/outline';
import { HomeIcon as HomeSolid, CogIcon as CogSolid } from '@heroicons/react/24/solid';
const navItems = [
{ name: 'ホーム', href: '/', outline: HomeOutline, solid: HomeSolid },
{ name: '設定', href: '/settings', outline: CogOutline, solid: CogSolid },
];
export function Sidebar({ currentPath }: { currentPath: string }) {
return (
<nav className="space-y-1">
{navItems.map((item) => {
const active = currentPath === item.href;
const Icon = active ? item.solid : item.outline;
return (
<a
key={item.href}
href={item.href}
className={`flex items-center gap-3 rounded-lg px-3 py-2 ${
active ? 'bg-indigo-50 text-indigo-600' : 'text-gray-600 hover:bg-gray-50'
}`}
>
<Icon className="size-6" />
{item.name}
</a>
);
})}
</nav>
);
}
フォームのバリデーション表示
miniスタイル(20px)は入力欄などの小さなスペースにぴったりです。
import { ExclamationCircleIcon } from '@heroicons/react/20/solid';
export function EmailField({ error }: { error?: string }) {
return (
<div>
<label htmlFor="email" className="block text-sm font-medium">
メールアドレス
</label>
<div className="relative mt-1">
<input
id="email"
type="email"
className={`block w-full rounded-md border px-3 py-2 pr-10 ${
error ? 'border-red-300' : 'border-gray-300'
}`}
/>
{error && (
<ExclamationCircleIcon className="absolute right-3 top-2.5 size-5 text-red-500" />
)}
</div>
{error && <p className="mt-1 text-sm text-red-600">{error}</p>}
</div>
);
}
アクセシビリティへの配慮
Heroiconsのコンポーネントは装飾用SVGとしてaria-hiddenを付けるのが基本です。アイコンのみのボタンでは、ボタン側にラベルを付けましょう。
import { XMarkIcon } from '@heroicons/react/24/outline';
<button type="button" aria-label="閉じる" className="rounded p-1 hover:bg-gray-100">
<XMarkIcon aria-hidden="true" className="size-6" />
</button>
aria-labelがあれば、スクリーンリーダーのユーザーにもボタンの意味が正しく伝わります。
まとめ
Heroiconsは、「高品質」「無料」「導入が簡単」の三拍子がそろったアイコンライブラリです。この記事のポイントを振り返ってみましょう。
- Tailwind Labs製のSVGアイコンライブラリで、MITライセンスで商用利用も可能です
- outline / solid / mini / microの4スタイルを、UIの密度や状態に応じて使い分けられます
- React・Vueでは公式パッケージからコンポーネントとしてインポートするだけで使えます
currentColorベースなので、テキスト色のクラス1つで色をコントロールできます
まずは公式サイトでアイコンを眺めて、お気に入りのアイコンをプロジェクトに追加してみてください。Tailwind CSSと組み合わせれば、統一感のある美しいUIがすぐに手に入ります。同じTailwind Labs製のHeadless UIと組み合わせるのもおすすめです。