やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

HTMLでパス指定する3つの方法(絶対パス、ルート相対パス、ファイル相対パス)

 2つの相対パスがあって混乱したのでまとめた。

方法

 HTMLでパスを指定するときは以下のちがいを理解しておく必要がある。

パス表記方法 HTML内パス URLが{base_url}/about/時のHTML内パス
絶対パス {base_url}/css/style.css {base_url}/css/style.css
ルート相対パス /css/style.css {base_url}/css/style.css
ファイル相対パス css/style.css
./css/style.css
../css/style.css
{base_url}/about/css/style.css
{base_url}/about/css/style.css
{base_url}/css/style.css

背景

 静的サイトジェネレータzolaは、おなじページを以下のような異なるURLで参照できてしまう。

  • {base_url}/about
  • {base_url}/about/

 このときファイル相対パスだと、一階層分../の違いが生じてパスが変化し参照できなくなってしまうことがある。

使い分け

方法 動機
絶対パス 異なる階層から参照されうる。
ルート相対パス ドメインを省略したい。異なる階層から参照される。
ファイル相対パス パスも省略したい。同じ階層からしか参照されない。
<link rel="stylesheet" href="https://example.com/css/style.css"><!--絶対パス-->
<link rel="stylesheet" href="/css/style.css"><!--ルート相対パス-->
<link rel="stylesheet" href="css/style.css"><!--ファイル相対パス-->
<link rel="stylesheet" href="./css/style.css"><!--ファイル相対パス-->
<link rel="stylesheet" href="../css/style.css"><!--ファイル相対パス-->

 zolaではルート相対パスを使うべき。なぜならzolaのページは必ず、末尾に/がつくときとつかないときの2種類ある。よって異なる階層から参照されることを想定したパス指定にすべきだ。

HTMLにおけるURL参照

 これはzolaのせいではなくHTMLやURLの参照仕様だと思われる。そこで、あらためてHTMLにおけるURL参照について整理してみた。

 {base_url}=https://example.comとする。このときstyle.cssファイルへのURL指定方法は以下の4通りある。

パス 意味
style.css 現在HTMLが存在するディレクトリからの相対パス
./style.css 現在HTMLが存在するディレクトリからの相対パス
/style.css {base_url}からの相対パス
https://example.com/style.css 絶対パス

 絶対パスは明確だからわかりやすい。これを使えば今回の罠にかかることもない。ただ、ドメイン名が変更されたりしたときなどで変更が面倒になる。なので相対パスを使いたい。だが、その相対パスが厄介だ。

相対パス

 問題は相対パスだ。わずかな表現のちがいでありながら、まったくことなるパスを指す。これがじつに紛らわしい。

パス 意味
/style.css {base_url}からの相対パス
style.css 現在HTMLが存在するディレクトリからの相対パス
./style.css 現在HTMLが存在するディレクトリからの相対パス

 さらにまとめてみる。

 相対パスには2種類ある。基準となるパスが違う。

基準 URL先頭
ルートディレクトリ({base_url}) /
現在HTMLディレクト なにもつけない or ./

 Linuxファイルシステムに似ている。ルートは/で表現されるから。先頭/相対パスドメイン名を省略できるものだと覚えておけばいい。

 URLが{base_url}/about/だとしたら、以下のようになる。

相対パス 参照パス
/style.css {base_url}/style.css
style.css {base_url}/about/style.css
./style.css {base_url}/about/style.css

 現在HTMLが存在するディレクトリを基準にして、その親をたどっていくパス指定もできる。

パス 意味
../style.css 現在HTMLが存在するディレクトリからの相対パス(親ディレクトリ)
../../style.css 現在HTMLが存在するディレクトリからの相対パス(2親ディレクトリ)

 たどる親の数だけ../を足していけばいい。

 区別するために名前をつける。

名前 URLが{base_url}/about/時のパス
ルート相対パス /style.css {base_url}/style.css
ファイル相対パス style.css
./style.css
../style.css
{base_url}/about/style.css
{base_url}/about/style.css
{base_url}/style.css

ファイル相対パス

<link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="./css/style.css">

 パスの先頭になにもつけないか./をつけると、現在ファイルがあるディレクトリからの相対パスになる。

 このとき、URLが{base_url}/のように末尾に/がつくとCSSが参照できなくなってしまう。なぜならつぎのようなパスになるからだ。

URL 参照パス
{base_url}/about {base_url}/css/style.css
{base_url}/about/ {base_url}/about/css/style.css

 実際にCSSが存在するパスは{base_url}/css/style.cssなので以下のようになる。

URL 参照パス 存在是非
{base_url}/about {base_url}/css/style.css
{base_url}/about/ {base_url}/about/css/style.css

 URL末尾に/があるかないか。それだけで参照できなくなってしまうバグとなる。もうそれだけでも大問題なのだが、さらに問題がある。

 以下のようにすれば一応、参照できる。

<!-- {base_url}/about -->
<link rel="stylesheet" href="css/style.css">
<!-- {base_url}/about/ -->
<link rel="stylesheet" href="../css/style.css">

 ただ、実際に存在しているのはひとつだけだ。それ以外のURLは参照エラーになってしまう。ブラウザの開発ツールでコンソールを開いたらエラーになっているのがわかる。キモチワルイ。

 よって、異なる階層から参照されるときはルート相対パスで指定すべきである。

ルート相対パス

<link rel="stylesheet" href="/css/style.css">

 パスの先頭に/をつけると、ルートからの相対パスになる。

 このときはURLの末尾に/があってもなくても、CSSを参照できる。

 なぜならURLに関わらずパスは必ず{base_url}/css/style.cssになるからだ。

結論

 異なる階層から参照されうるときはルート相対パスを使おう。

 つまるところ、URL指定するときは以下の要点を理解しておけばよい。

パス表記方法 HTML内パス URLが{base_url}/about/時のHTML内パス
絶対パス {base_url}/css/style.css {base_url}/css/style.css
ルート相対パス /css/style.css {base_url}/css/style.css
ファイル相対パス css/style.css
./css/style.css
../css/style.css
{base_url}/about/css/style.css
{base_url}/about/css/style.css
{base_url}/css/style.css

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux