5.

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

編集
この記事の要点
  • <base href="...">ページ内の相対 URL のベースを指定する HTML 要素
  • <head> 内に書く、同 1 ページに 1 つだけ
  • target 属性で全リンクのデフォルトターゲットを指定可(_blank 等)
  • 副作用: <a href="#section"> もベース URL からの絶対化扱いになり、ページ内アンカーが機能しなくなる
  • SPA(React Router 等)/ サブディレクトリ配置で活用されるが、多用は推奨されない

base 要素とは

HTML 文書内のすべての相対 URL のベースを指定する要素。<head> 内に 1 つだけ書けます。

<!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>

属性

属性意味
hrefベース URLhttps://cdn.example.com/v2/
target全リンクのデフォルトターゲット_blank / _self / _parent / _top / フレーム名

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

target 属性で全リンクを新タブに

<head>
  <base target="_blank">
</head>
<body>
  <a href="/about">About</a>
  <!-- → 自動的に新タブで開く -->

  <a href="/contact" target="_self">Contact</a>
  <!-- → target を個別指定すれば上書き可 -->
</body>

ドキュメントサイトやヘルプセンターで「全リンクを新タブで開きたい」用途に便利。ただしUX を損ねることが多いので注意。

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

最大の落とし穴<base href="https://example.com/"> を指定すると、<a href="#section">同ページ内のアンカーではなく https://example.com/#section への新規ナビゲーションになります:

<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='section'">
    セクション
  </a>
</body>

副作用2: フォーム送信先

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

SPA での活用例

React / Vue / Angular のシングルページアプリケーションで、サブディレクトリ配置するときに使われます:

<!-- /admin/ にデプロイした SPA -->
<head>
  <base href="/admin/">
</head>
<body>
  <!-- React Router で BrowserRouter basename と組み合わせ -->
  <div id="root"></div>
  <script src="js/app.js"></script>
</body>
// React Router
import { BrowserRouter } from 'react-router-dom';

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

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

// Angular
// angular.json の "baseHref": "/admin/" + index.html の <base href>

動的に base を変える

// JavaScript で base を変更
const base = document.querySelector('base');
if (base) {
    base.href = 'https://cdn-region-jp.example.com/';
} else {
    const newBase = document.createElement('base');
    newBase.href = 'https://cdn-region-jp.example.com/';
    document.head.prepend(newBase);
}

// 注意: すでにパース済の相対 URL(<img src> 等)は再評価されない
// → 動的に変えても効果は限定的

base を使う代替手段

用途base を使う代替
サブディレクトリ配置<base href="/admin/">絶対パス書く or サーバ側で配信パス調整
全リンクを新タブ<base target="_blank">JS で document.links ループ
CDN への切替base.href 変更ビルド時にパス置換
ローカル / 本番のパス切替環境別 base環境変数 + テンプレート

セキュリティ上の注意

XSS 攻撃で <base> を注入されると、すべての相対 URL リソース(JS / CSS / 画像)が攻撃者サーバから読まれる非常に危険なベクタになります。CSP で防御:

Content-Security-Policy: base-uri 'self'

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

歴史と互換性

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

非推奨なパターン

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

FAQ

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

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

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

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. html要素
  2. head要素
  3. body要素
  4. title要素
  5. base要素
  6. meta要素
  7. div要素
  8. span要素
  9. header要素
  10. HTML5 footer 要素の使い方(フッター・コピーライト・連絡先)
  11. main要素
  12. address要素

最近更新/作成されたページ