この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: base要素
SEOタイトル: HTML <base> 要素の使い方と落とし穴(相対 URL / アンカーリンク / target)

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li><strong><code><base href="..."></code></strong> は<strong>ページ内の相対 URL のベース</strong>を指定する HTML 要素</li><li><code><head></code> 内に書く、<strong>同 1 ページに 1 つだけ</strong></li><li><code>target</code> 属性で<strong>全リンクのデフォルトターゲット</strong>を指定可(<code>_blank</code> 等)</li><li><strong>副作用</strong>: <code><a href="#section"></code> もベース URL からの絶対化扱いになり、ページ内アンカーが機能しなくなる</li><li>SPA(React Router 等)/ サブディレクトリ配置で活用されるが、<strong>多用は推奨されない</strong></li></ul></td></tr></table>
<h2>base 要素とは</h2>

<p>HTML 文書内のすべての<strong>相対 URL のベース</strong>を指定する要素。<code><head></code> 内に 1 つだけ書けます。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!DOCTYPE html>
<html>
<head>
  <base href="https://example.com/docs/">
  <title>サンプル</title>
</head>
<body>
  <!-- 相対 URL は base からの解釈になる -->
  <a href="intro.html">はじめに</a>
  <!-- → https://example.com/docs/intro.html へ -->

  <img src="img/logo.png">
  <!-- → https://example.com/docs/img/logo.png を読み込む -->
</body>
</html></code></pre>
<h2>属性</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>属性</th><th>意味</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>href</code></td><td>ベース URL</td><td><code>https://cdn.example.com/v2/</code></td></tr>
<tr><td><code>target</code></td><td>全リンクのデフォルトターゲット</td><td><code>_blank</code> / <code>_self</code> / <code>_parent</code> / <code>_top</code> / フレーム名</td></tr>
</tbody>
</table>

<p>少なくともどちらか 1 つ指定が必要。両方指定も可。</p>

<h2>target 属性で全リンクを新タブに</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><head>
  <base target="_blank">
</head>
<body>
  <a href="/about">About</a>
  <!-- → 自動的に新タブで開く -->

  <a href="/contact" target="_self">Contact</a>
  <!-- → target を個別指定すれば上書き可 -->
</body></code></pre>
<p>ドキュメントサイトやヘルプセンターで「全リンクを新タブで開きたい」用途に便利。ただし<strong>UX を損ねる</strong>ことが多いので注意。</p>

<h2>副作用1: ページ内アンカーが効かなくなる</h2>

<p><strong>最大の落とし穴</strong>。<code><base href="https://example.com/"></code> を指定すると、<code><a href="#section"></code> が<strong>同ページ内のアンカー</strong>ではなく <code>https://example.com/#section</code> への新規ナビゲーションになります:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><head>
  <base href="https://example.com/docs/">
</head>
<body>
  <!-- ❌ 現在のページが /docs/help.html だとしても -->
  <!--    https://example.com/docs/#section に飛ばされる -->
  <a href="#section">セクション</a>

  <!-- ✅ 回避: 明示的にパスを書く -->
  <a href="help.html#section">セクション</a>

  <!-- ✅ 回避: JavaScript で動的に -->
  <a href="" onclick="event.preventDefault(); location.hash=&apos;section&apos;">
    セクション
  </a>
</body></code></pre>
<h2>副作用2: フォーム送信先</h2>

<p>同様に <code><form action="/submit"></code> も base からの解釈になります。意図しないエンドポイントに POST される可能性があります。</p>

<h2>SPA での活用例</h2>

<p>React / Vue / Angular のシングルページアプリケーションで、<strong>サブディレクトリ配置</strong>するときに使われます:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-html"><!-- /admin/ にデプロイした SPA -->
<head>
  <base href="/admin/">
</head>
<body>
  <!-- React Router で BrowserRouter basename と組み合わせ -->
  <div id="root"></div>
  <script src="js/app.js"></script>
</body></code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// React Router
import { BrowserRouter } from &apos;react-router-dom&apos;;

// public/index.html に <base href="/admin/"> がある場合
<BrowserRouter basename="/admin">
  <Routes>...</Routes>
</BrowserRouter>

// Vue Router
const router = createRouter({
  history: createWebHistory(&apos;/admin/&apos;),
  routes: [...]
});

// Angular
// angular.json の "baseHref": "/admin/" + index.html の <base href></code></pre>
<h2>動的に base を変える</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-javascript">// JavaScript で base を変更
const base = document.querySelector(&apos;base&apos;);
if (base) {
    base.href = &apos;https://cdn-region-jp.example.com/&apos;;
} else {
    const newBase = document.createElement(&apos;base&apos;);
    newBase.href = &apos;https://cdn-region-jp.example.com/&apos;;
    document.head.prepend(newBase);
}

// 注意: すでにパース済の相対 URL(<img src> 等)は再評価されない
// → 動的に変えても効果は限定的</code></pre>
<h2>base を使う代替手段</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e8f5e9"><th>用途</th><th>base を使う</th><th>代替</th></tr></thead>
<tbody>
<tr><td>サブディレクトリ配置</td><td><code><base href="/admin/"></code></td><td>絶対パス書く or サーバ側で配信パス調整</td></tr>
<tr><td>全リンクを新タブ</td><td><code><base target="_blank"></code></td><td>JS で <code>document.links</code> ループ</td></tr>
<tr><td>CDN への切替</td><td>base.href 変更</td><td>ビルド時にパス置換</td></tr>
<tr><td>ローカル / 本番のパス切替</td><td>環境別 base</td><td>環境変数 + テンプレート</td></tr>
</tbody>
</table>

<h2>セキュリティ上の注意</h2>

<p>XSS 攻撃で <code><base></code> を注入されると、すべての相対 URL リソース(JS / CSS / 画像)が攻撃者サーバから読まれる<strong>非常に危険</strong>なベクタになります。CSP で防御:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-http">Content-Security-Policy: base-uri &apos;self&apos;

# base 要素の href として許可するオリジンを制限
# 攻撃者が <base href="https://evil.com/"> を注入できなくなる</code></pre>
<h2>歴史と互換性</h2>

<ul>
<li><strong>HTML2.0</strong> (1995) で導入</li>
<li>当初は <code>href</code> のみ。<code>target</code> は HTML4 で追加</li>
<li>すべてのブラウザで対応(IE 含む)</li>
<li>HTML5 仕様で「1 ページに 1 つだけ」が明文化</li>
</ul>

<h2>非推奨なパターン</h2>

<ul>
<li><strong>本文中で href 切替のためだけに base</strong> → 絶対 URL を書いた方が明確</li>
<li><strong>SEO 対策で base を使う</strong> → 検索エンジンに canonical URL を伝えるなら <code><link rel="canonical"></code> を使う</li>
<li><strong>JS で頻繁に base を書き換える</strong> → SPA ルーターを使う</li>
<li><strong>iframe 内に異なる base</strong> → 親フレームと混乱の元</li>
</ul>

<h2>FAQ</h2>

<p><strong>Q: 同 1 ページに複数の <code><base></code> を書ける?</strong><br />
A: HTML5 仕様で<strong>1 つだけ</strong>と明記。複数あるとブラウザは最初の 1 つを採用、それ以外を無視します。</p>

<p><strong>Q: base を使うと相対 URL の動作が変</strong><br />
A: base が想定通り効いている可能性大。<code>view-source:</code> でレンダリング後の URL を確認、ブラウザ DevTools の Network タブで実際のリクエスト URL をチェックしましょう。</p>

<p><strong>Q: SPA で BrowserRouter の basename と <code><base></code> どちらが必要?</strong><br />
A: <strong>両方推奨</strong>。<code><base></code> は<strong>静的アセット(CSS/JS/画像)</strong>の相対パス、<code>basename</code> は<strong>ルーティング</strong>を担当します。</p>