見出しアンカーは必要?長い記事の移動・共有で役立つ場面と増やしすぎるデメリット
AstroはMarkdown見出しへ自動でIDを付けるため、追加プラグインなしでもページ内アンカーを使えます。長い技術記事の目次や特定セクション共有で役立つ一方、見出し変更によるURL切れ、UIの増加、固定ヘッダーやコピー機能の注意点もあります。

長い技術記事を読んでいると、「この記事を見て」ではなく「この見出しのところを見て」と伝えたい場面がある。
URLが記事の先頭だけを指していると、共有された側はページを開いたあとに目次や本文から対象箇所を探す必要がある。
アンカーリンクがあると、
https://example.com/blog/article/#使う場面
のように、記事の中の特定セクションをURLで指定できる。
ゆまラボではすでに記事上部に目次があり、長い記事ほど見出し単位で移動する機会が増えている。現在のAstroではMarkdownの見出しへIDが自動で付くため、ページ内リンクの土台自体はすでにある。
追加を検討するなら、「アンカーリンクそのものを使えるようにする」というより、見出し横のリンクやURLコピーボタンを見せ、読者がその機能を使いやすくするかが論点になる。
AstroではMarkdown見出しにIDが自動で付く#
Astro公式ドキュメントでは、MarkdownとMDXの見出しにid属性が自動で付与される。
例えばMarkdownに、
## 使う場面
があれば、生成HTMLには見出しIDが入り、URL末尾へ#...を付けることでその位置へ移動できる。
Astroは見出しIDの生成にgithub-sluggerを使っている。Content Collectionsで記事をrender()した場合も、見出し情報には生成されたslugが含まれる。
そのため、単純なページ内リンクだけならJavaScriptは必要ない。
<a href="#使う場面">使う場面へ</a>
のような通常のリンクで動く。
ブラウザ側では#以降をfragment identifierとして扱う。MDNの説明では、このfragmentはサーバーへ送られず、ページを取得した後にブラウザが対象IDへ移動する。

※ 記事内の図は内容を整理するために作成した概念図です。各社の公式資料や実際の製品画面ではありません。
現在のゆまラボに目次があるなら、各項目から見出しへ移動する仕組みはこのIDをそのまま使える。
見出し横へ鎖アイコンを追加したり、「この見出しのURLをコピー」を付けたりする場合も、生成済みIDを再利用できる。
使いやすいのは長い記事と一部分だけ共有したい場面#
アンカーリンクが特に効くのは、本文全体を上から読まなくてもよい記事。
技術ブログではかなり該当する。
例えばエラー対応の記事に、
症状
原因
修正方法
確認方法
があるとする。
同僚やSNSで伝えたいのが「確認方法」だけなら、記事トップのURLを送るより、
/blog/example/#確認方法
を送った方が早い。
設定手順の記事でも同じ。
「この手順の3番だけ見てほしい」という用途では、見出しを直接開ける方が相手の探索が少なくなる。
ゆまラボのように1記事が長くなりやすく、目次も表示しているサイトでは、
目次
→ 読者が記事内を移動する
見出しアンカー
→ 記事外からその位置へ直接入る
という役割分担になる。
FAQや用語集のように、1ページの中へ複数の独立した回答を置くページとも相性がよい。
逆に、2~3見出ししかない短い記事では効果が小さい。記事先頭から対象箇所まで数秒で読めるなら、見出し横へボタンを増やす方が目立つ場合もある。
URLコピーまで付けるなら少し実装が増える#
見出し自体へ普通のアンカーリンクを付けるだけならHTMLで済む。
「クリックしたら、その見出しを含む完全なURLをクリップボードへコピーする」となると、Clipboard APIを使う形になる。
例えば処理の考え方は次の程度。
const url = new URL(window.location.href);
url.hash = headingId;
await navigator.clipboard.writeText(url.toString());
navigator.clipboard.writeText()は現在広く利用できるが、MDNではsecure context、つまりHTTPSで使うAPIとして案内されている。
bringain.comはHTTPSなので本番環境とは相性がよい。
ただし、コピー処理が失敗する可能性は残る。
そのため実装するなら、
見出しアンカーそのもの
→ 通常の<a href="#id">
URLコピーボタン
→ JavaScript + Clipboard API
を分けた方が扱いやすい。
コピーに失敗してもページ内リンクまで使えなくなる構成にはしない。
見出し横をクリックしたらURLのhashだけ変わり、そこからブラウザのアドレスバーをコピーできる状態でも最低限の目的は達成できる。
見出しを変更すると共有済みURLが古くなる#
デメリットで一番気になるのはここ。
Astroの見出しIDは見出しテキストから生成される。
例えば、
## 使うメリット
から生成されたIDを外部へ共有したあと、見出しを、
## アンカーリンクを使う利点
へ変更すると、生成IDも変わる可能性がある。
古いURLはページ自体にはアクセスできるが、該当IDがなくなれば期待した見出し位置へ移動できない。
ページの404にはならないので、普通のリンク切れより気付きにくい。
ゆまラボでは内部リンクの404をビルド時に確認する仕組みをすでに入れているが、その検査ではquery stringとhash fragmentを外し、ページ本体が存在するかを確認している。見出しIDの存在確認までは対象にしていない。
つまり、
/blog/example/#old-heading
の/blog/example/が存在していれば、現在の内部リンクチェックは成功する。
実際の#old-headingが消えていても検出できない。
アンカーリンクを積極的に使うなら、これは運用上の弱点になる。
対処方法は大きく2つ。
1つは、公開後に見出し文言をむやみに変更しないこと。
もう1つは、将来アンカーリンクの利用が増えた段階で、内部リンクチェッカーへfragment IDの存在確認を追加すること。
最初からそこまで作る必要はないが、「通常リンクの404チェックでアンカー切れまで守られる」とは考えない方がよい。
同じ見出し名と日本語IDも確認しておきたい#
見出しIDを自動生成する場合、記事側でIDを毎回考えなくてよい。
その代わり、自動生成規則に依存する。
同じ見出しが複数回ある場合は、一意になるようIDへsuffixが付く。
記事へ後から同名見出しを追加したり、見出し順を変更したりすると、共有済みfragmentとの関係を確認した方がよい。
日本語見出しもアンカーにできる。
Astro公式の日本語ドキュメントでも、日本語見出しへ#はじめにのように直接リンクする例が載っている。
ブラウザやコピー先ではURLエンコードされた長い文字列として見えることがあるので、
#使う場面
が常にそのまま読みやすく表示されるとは限らない。
技術的には問題なくても、SNSやメールへ貼ったURLが長く見える点はデメリットになる。
このため「URLを短くしたいから全部英語IDへ手動変更する」という判断もできるが、そうすると今度はID管理が別作業になる。
ゆまラボではまずAstro標準IDを使い、問題が出てから個別対応する方が負担は少ない。
固定ヘッダーがあると見出しが隠れることがある#
ページ内リンクで対象見出しへ移動したとき、ブラウザは対象要素を画面上部へ寄せる。
サイト上部にposition: stickyや固定ヘッダーがあると、移動先の見出しがヘッダーの下へ隠れる場合がある。
これは機能としてリンクが壊れているわけではないので、実装後の確認で見落としやすい。
CSSでは対象見出しへ、
article :is(h2, h3) {
scroll-margin-top: 6rem;
}
のように余白を指定できる。
MDNでもscroll-margin-topは固定ヘッダーがある場合の位置調整に利用できるとしている。
ゆまラボへ見出しアンカーUIを付けるなら、PCだけでなくスマホでも、
目次から移動
見出し横のアンカーから移動
外部から#fragment付きURLを直接開く
の3パターンを見る。
見出しタイトルが画面外やヘッダー裏へ入らないことを確認したい。
アンカーアイコンを全見出しへ出すと本文がうるさくなる#
機能として便利でも、見出しのたびに鎖アイコンや「URLコピー」を常時表示すると、記事の見え方は変わる。
特にスマホでは見出し幅が狭い。
長い日本語見出しの横へアイコンを固定すると、
見出しが不自然に改行される
アイコンだけ次の行へ落ちる
タップ領域が本文へ近づく
といった問題が出る。
技術記事で一番読ませたいのは見出し名なので、アンカーUIを目立たせすぎない方がよい。
実装候補としては、
PC
→ 見出しhover時だけ表示
スマホ
→ 小さく常時表示、または見出しタップとは別領域
目次
→ 従来どおりテキストリンク
のような方法がある。
ただしhoverだけにすると、タッチ端末では発見しにくい。
「常時表示かhoverか」に正解があるわけではない。
ゆまラボでは実装前後をスマホで見て、見出しの読みやすさを優先して決める方がよさそうだ。
短い記事まで一律に表示する必要もない。
ゆまラボでは追加する価値があるが、機能は小さくしたい#
現在のゆまラボは記事数が増え、1記事あたりの内容も長くなっている。
目次がすでにあり、Astro側の見出しIDも標準で生成される。
この状態なら、アンカーリンクを使うための土台を新しく作る必要はほとんどない。
追加するなら、
見出し横へ小さなリンク操作を追加
↓
クリックで#fragmentへ移動
↓
必要ならURLをコピー
程度でよい。
使いどころは、長い技術記事の一部分を共有するとき。
特に設定値、エラー対応、比較表、確認手順など、「記事全体ではなくこの節を見てほしい」と伝える場面では分かりやすい。
一方、導入すると見出しIDも公開URLの一部として扱うことになる。
見出し変更、同名見出し、固定ヘッダー、スマホ表示、コピー失敗、現在のリンクチェッカーがfragmentを検査しない点は確認対象になる。
アンカーリンク自体は小さな機能だが、共有したURLを長く残すなら見出し名も少し変更しにくくなる。
ゆまラボでは「全見出しを強く装飾する機能」ではなく、「必要なときにその節を共有できる小さな操作」として追加するのが合いそうだ。


