Laravelでファビコンを設定する方法|Blade・Vite・Inertia.js対応【2026年版】
Laravelプロジェクトにファビコンを設定する
Laravelでファビコンを設定する方法は、基本的にはシンプルです。public/ ディレクトリにファイルを配置し、Bladeテンプレートに <link> タグを追加するだけで完了します。
ただし、Vite連携、Inertia.js/LivewireによるSPA化、環境別ファビコン、PWA対応など、モダンなLaravelプロジェクトでは考慮すべきポイントがいくつかあります。
この記事では、基本の設定から応用パターンまでを段階的に解説します。
事前準備:ファビコンファイルを用意する
まず、ファビコン用のファイルを準備します。2026年の推奨構成は以下の3ファイルです。
| ファイル | 用途 | サイズ |
|---|---|---|
favicon.ico | レガシーブラウザ対応 | 16+32+48のマルチサイズ |
favicon.svg | モダンブラウザ用 | ベクター(サイズ不問) |
apple-touch-icon.png | iOSホーム画面 | 180x180px |
さらにPWA対応が必要な場合は、192x192と512x512のPNG、site.webmanifest も用意します。
当サイトのアプリアイコン一括生成ツールを使えば、1枚の画像から全ファイルをまとめて生成できます。

各ファイル形式の違いやブラウザ対応状況は以下を参照してください。
基本の設定:publicディレクトリ + Bladeテンプレート
ステップ1:ファイルを配置する
ファビコンファイルを public/ ディレクトリの直下に配置します。
public/
favicon.ico
favicon.svg
apple-touch-icon.png
site.webmanifest # PWA対応する場合
web-app-manifest-192x192.png # PWA対応する場合
web-app-manifest-512x512.png # PWA対応する場合
public/ に置いたファイルはLaravelのルーティングを通さず、Webサーバーから直接配信されます。ブラウザは自動的に /favicon.ico へリクエストを送るため、ルート直下に配置するのが重要です。
ステップ2:Bladeレイアウトにlinkタグを追加する
メインのレイアウトファイル(通常は resources/views/layouts/app.blade.php)の <head> 内に以下を追加します。
<!-- ファビコン -->
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
<link rel="icon" href="{{ asset('favicon.svg') }}" type="image/svg+xml">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">
asset() ヘルパーは、public/ ディレクトリ内のファイルへの完全なURLを生成します。APP_URL や ASSET_URL 環境変数を考慮してくれるため、CDN配信時にも対応できます。
なぜ sizes="any" を指定するのか
ICOファイルに sizes="48x48" のような具体的なサイズを指定すると、Chromeがサイズ比較の結果SVGよりICOを優先してしまう既知の問題があります。sizes="any" を指定することで、SVG対応ブラウザではSVGが優先されるようになります。
Viteとの関係
Laravel 9.19以降(Laravel 10/11/12)では、フロントエンドのビルドツールとしてViteがデフォルトです。Viteとファビコンの関係を理解しておくことは重要です。
ファビコンはViteのビルド対象にしない
Viteは resources/ 配下のファイルをバンドル・ハッシュ化して public/build/ に出力します。しかし、ファビコンはViteを通すべきではありません。
- ファビコンのURLはブラウザにキャッシュされるため、URLが安定している必要がある
- Viteがハッシュを付けると
favicon-abc123.icoのようなURLになり、キャッシュバスター以外の問題を引き起こす - ブラウザは
/favicon.icoを自動リクエストするため、固定パスでなければならない
正しいアプローチ: ファビコンは public/ に直接配置し、asset() ヘルパーで参照する。Vite::asset() は使わない。
{{-- NG: Vite経由(ハッシュ化されてしまう) --}}
<link rel="icon" href="{{ Vite::asset('resources/images/favicon.ico') }}">
{{-- OK: publicディレクトリから直接配信 --}}
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
@viteディレクティブとの共存
@vite ディレクティブはCSS/JSの読み込み用です。ファビコンの <link> タグとは独立しているので、同じ <head> 内に並べて問題ありません。
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- ファビコン -->
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
<link rel="icon" href="{{ asset('favicon.svg') }}" type="image/svg+xml">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">
<!-- Vite管理のCSS/JS -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
Inertia.jsでの設定
Inertia.js(Vue/React)を使ったSPAでも、ファビコンの基本的な設定方法は変わりません。Inertiaのルートテンプレートである resources/views/app.blade.php の <head> にlinkタグを追加します。
<!-- resources/views/app.blade.php -->
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
<link rel="icon" href="{{ asset('favicon.svg') }}" type="image/svg+xml">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">
@inertiaHead
@vite(['resources/js/app.js'])
</head>
Inertia Headコンポーネントでの動的変更
Inertia.jsの <Head> コンポーネントを使えば、ページごとにファビコンを動的に変更することもできます。
Vue 3の場合:
<script setup>
import { Head } from '@inertiajs/vue3'
</script>
<template>
<Head>
<link head-key="favicon" rel="icon" type="image/svg+xml" href="/favicon-special.svg" />
</Head>
</template>
Reactの場合:
import { Head } from '@inertiajs/react'
export default function SpecialPage() {
return (
<>
<Head>
<link head-key="favicon" rel="icon" type="image/svg+xml" href="/favicon-special.svg" />
</Head>
{/* ページコンテンツ */}
</>
)
}
head-key="favicon" を指定すると、同じキーのタグが重複せず上書きされます。
Livewireでの設定
Livewire(v3/v4)を使ったアプリケーションでも、ファビコンの設定はBladeレイアウトの <head> に記述するだけです。
<!-- resources/views/layouts/app.blade.php -->
<head>
<link rel="icon" href="{{ asset('favicon.ico') }}" sizes="any">
<link rel="icon" href="{{ asset('favicon.svg') }}" type="image/svg+xml">
<link rel="apple-touch-icon" href="{{ asset('apple-touch-icon.png') }}">
@livewireStyles
</head>
Livewire 3以降の wire:navigate によるSPAナビゲーションでは、<head> 内のlinkタグは初回読み込み時に設定されたものがページ遷移を通じて保持されます。ファビコンが遷移のたびにちらつくことはありません。
環境別ファビコン(dev / staging / production)
開発中に複数の環境(ローカル、ステージング、本番)を同時にブラウザで開くと、どのタブがどの環境かわからなくなることがあります。環境別のファビコンを設定すると、一目で区別できます。
beyondcode/laravel-favicon パッケージ
beyondcode/laravel-favicon は、ファビコンに環境名のラベルを自動でオーバーレイしてくれるパッケージです。
インストール:
composer require beyondcode/laravel-favicon
設定ファイルを公開:
php artisan vendor:publish --provider='BeyondCode\LaravelFavicon\FaviconServiceProvider' --tag='config'
Bladeでの使い方:
asset() の代わりに favicon() ヘルパーで囲むだけです。
<link rel="icon" href="{{ favicon(asset('favicon.ico')) }}" sizes="any">
<link rel="icon" type="image/svg+xml" href="{{ favicon(asset('favicon.svg')) }}">
config/favicon.php で環境ごとの表示を設定:
'enabled_environments' => [
'local' => [
'text' => 'DEV',
'color' => '#000000',
'background_color' => '#ffffff',
],
'staging' => [
'text' => 'STG',
'color' => '#ffffff',
'background_color' => '#ff0000',
],
],
local 環境ではファビコンに「DEV」、staging では赤背景に「STG」というラベルが自動的にオーバーレイされます。production 環境(enabled_environments に含まれない環境)では元のファビコンがそのまま表示されるため、本番環境へのパフォーマンス影響はゼロです。
PWA対応(Web App Manifest)
LaravelアプリケーションをPWAとしてインストール可能にする場合は、site.webmanifest を用意します。
手動で設定する場合
public/site.webmanifest を作成します。
{
"name": "サイト名",
"short_name": "短い名前",
"icons": [
{
"src": "/web-app-manifest-192x192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/web-app-manifest-512x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
}
],
"theme_color": "#1a1065",
"background_color": "#ffffff",
"display": "standalone",
"start_url": "/"
}
Bladeレイアウトに参照を追加します。
<link rel="manifest" href="{{ asset('site.webmanifest') }}">
purpose: "maskable" を指定すると、Android 13以降でアイコンが自動的に丸くクリッピングされます。maskable用の画像は周囲にパディングを多めに確保してください。
トラブルシューティング
ファビコンが表示されない
- ファイルが
public/に存在するか確認:php artisan serveでhttp://localhost:8000/favicon.icoにアクセスして画像が表示されるか - Bladeテンプレートのlinkタグを確認:DevToolsのElementsタブで
<link rel="icon">が出力されているか - ブラウザキャッシュ:シークレットモードで確認、スーパーリロード(Ctrl+Shift+R)
HTTPS環境でファビコンが読み込めない(Mixed Content)
ロードバランサーやリバースプロキシの背後でSSLを終端している場合、asset() が http:// のURLを生成し、Mixed Contentエラーになることがあります。
対処法(いずれか1つ):
// AppServiceProvider の boot() に追加
URL::forceScheme('https');
# .env
APP_URL=https://your-domain.com
ASSET_URL=https://your-domain.com
Laravel Octane使用時の注意
Laravel Octaneで Webサーバーなし(Octane単体)で動作させている場合、public/ の静的ファイルが正しく配信されないことがあります。Nginx/Caddyをフロントに置いて静的ファイルは直接配信する構成が推奨です。
favicon.icoの404エラーがログに出る
ブラウザは <link> タグの有無にかかわらず /favicon.ico を自動リクエストします。ファイルがないと404エラーがアクセスログに記録され続けます。public/favicon.ico を配置すれば解消します。
ファビコンを更新したのに古いアイコンが表示される(キャッシュバスター)
ブラウザはファビコンを強くキャッシュするため、ファイルを差し替えただけでは反映されないことがあります。URLにクエリパラメータを付けてキャッシュを強制的に無効化するのが最も確実な方法です。
<link rel="icon" href="{{ asset('favicon.ico') }}?v={{ config('app.version', '1') }}" sizes="any">
config/app.php にバージョンを定義しておけば、デプロイ時にバージョンを上げるだけで全ユーザーのキャッシュが更新されます。
// config/app.php
'version' => '2.0',
スーパーリロード(Ctrl+Shift+R)やシークレットモードでの確認も併用してください。
ファビコンが表示されない場合の総合的な対処法は以下の記事で詳しく解説しています。
よくある質問(FAQ)
Q. Laravel MixからViteに移行した場合、ファビコンの設定は変わる?
ファビコンを public/ に配置して asset() で参照している場合は変更不要です。Mix時代に resources/ 配下でViteのビルドパイプラインを通していた場合のみ、public/ への移動が必要です。
Q. SVGファビコンを使いたい場合はどうする?
public/favicon.svg にSVGファイルを配置し、Bladeに以下を追加します。
<link rel="icon" href="{{ asset('favicon.svg') }}" type="image/svg+xml">
SVGファビコンの作り方やダークモード対応は以下の記事で詳しく解説しています。
Q. 他のフレームワークでの設定方法は?
Next.js、React、Vue.js/Nuxtでのファビコン設定は以下の記事で解説しています。
まとめ
| 環境 | 設定方法 |
|---|---|
| 基本(Blade) | public/ にファイル配置 + asset() でlinkタグ |
| Vite連携 | Viteを通さず public/ に直接配置 |
| Inertia.js | ルートBlade(app.blade.php)のheadに記述 |
| Livewire | レイアウトBladeのheadに記述 |
| 環境別表示 | beyondcode/laravel-favicon パッケージ |
| PWA対応 | site.webmanifest + 192/512px PNG |
最小構成なら、public/favicon.ico を配置してBladeに1行追加するだけです。モダンな構成にするなら、SVGファビコンとApple Touch Iconも追加しましょう。
ファビコンの画像がまだない方はこちらから作成できます。
全プラットフォームのアイコンを一括で生成したい場合はこちら。
この記事を書いた人
Favicon作成ツール 編集チーム
月間数十万人が利用するWebツールを開発・運営するチームです。ファビコンの作成・変換・設定に関する実践的なノウハウを、現場の経験をもとに発信しています。