読み込み中...

HTMLでアンカーリンクの使い方を実践する方法10選

初心者向けHTMLアンカー使い方解説 HTML
この記事は約26分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

HTMLの<a>要素とid属性を組み合わせると、同じページ内の見出し、フォーム、FAQ、タブ風UIなどへ直接移動できます。長いページほど目的地までの距離が伸びるため、アンカーリンクを適切に置くと読者が必要な情報へ迷わず到達しやすくなります。

その使い方で特に押さえたいのは、リンク側のhref="#name"と移動先のid="name"を一致させる点です。プログラミング初心者がつまずきやすいのは、#の付け忘れ、idの重複、固定ヘッダーに見出しが隠れる問題だと言えるでしょう。

動作確認環境
  • HTML Living Standard
  • CSS Snapshot 2023
  • Google Chrome 126 / Mozilla Firefox 127 / Safari 17
  • JavaScript ECMAScript 2023 相当

公式ドキュメントによれば、<a>要素はhref属性によって別URLだけでなくページ内フラグメントへも移動できます。仕様や属性の詳細はMDNのa要素リファレンスWHATWG HTMLのa要素仕様が一次情報として参照しやすい資料です。

📖 この記事で学べること
  • HTMLでアンカーリンクを作る基本構文
  • hrefidを対応させる実践的な使い方
  • ナビゲーション、FAQ、タブ風UIでの活用法
  • CSSとJavaScriptを組み合わせたサンプルコード
  • リンク切れ、位置ずれ、イベント競合の直し方

HTMLアンカーリンクの基本

結論から言えば、HTMLのアンカーリンクは<a href="#target">id="target"の対応で成立します。この対応関係が崩れない限り、ページ上部の目次から本文見出しへ移動する使い方も、問い合わせフォームへ誘導する活用法も同じ考え方で扱えます。

<nav aria-label="ページ内メニュー">
  <a href="#profile">プロフィールへ移動</a>
</nav>

<section id="profile">
  <h2>プロフィール</h2>
  <p>この位置がリンク先です。</p>
</section>

結果: 期待される表示は、「プロフィールへ移動」を選ぶとid="profile"を持つ<section>付近へスクロールする状態です。

このとき、リンク側には#profileのように#を付け、移動先のidには#を付けません。両者の文字列は大文字小文字も含めて照合されるため、#Profileid="profile"のような差があると意図した位置へ移動できない場合があります。

一般に、ページ内リンクは目次、固定ヘッダー、記事末尾の関連導線、フォームへの誘導に向いています。たとえばHTMLでカレンダーUIを作る場合も、日付一覧から詳細欄へ移動する導線としてアンカーリンクを組み込めますし、ここがポイントです。関連する実装例はHTMLとJSを使ってカレンダーを作成・更新する方法10選も参考になるのが基本です。

💡 Tips: id名は意味が伝わる英数字にすると保守しやすくなるのが基本です。section1よりcontact-formprice-listのほうが、後から読んだときに目的地を判断しやすいでしょう。
項目主な書き方用途注意点関連する語
ページ内移動href="#intro"同一ページの見出しへ移動idと完全一致させるアンカーリンク
移動先IDid="intro"ジャンプ先を定義同一文書で重複させないid
外部ページの位置page.html#faq別ページの途中へ誘導移動先ページにIDが必要fragment
目次<nav>内のリンク長文ページの回遊を支援aria-labelを付ける<nav>
見出し<h2 id="x">セクション単位で移動見出し文とIDを分けて考える<h2>
フォーム誘導href="#contact"問い合わせ欄へ移動送信処理とは分離する<form>
固定ヘッダー対策scroll-margin-top見出しの隠れを防ぐヘッダー高に合わせるCSS
滑らかな移動scroll-behavior: smoothスクロールの動きを緩やかにする動きが苦手な利用者に配慮するscroll-behavior
クリック制御addEventListener独自処理を追加preventDefaultの扱いに注意JavaScript
対象取得querySelectorIDに合う要素を探す存在確認を入れるDOM
表示切替classList.toggleタブやアコーディオンを制御状態クラスを整理するclass
非表示hidden不要な内容を隠す支援技術への影響も考えるhidden
視覚効果:hoverポインター通過時の反応キーボード操作にも対応する:focus-visible
リンク装飾text-decoration下線の有無を調整リンク判別性を落とさないcolor
colorリンク文字色を変えるコントラストを確保するbackground-color
余白paddingクリック領域を広げる周辺要素との距離を見るmargin
リスト型ナビ<ul><li>複数リンクを整理順序が必要なら<ol>list-style
ページ上部へ戻るhref="#top"長いページの復帰導線冒頭にid="top"を置く使い方
FAQ移動href="#q1"質問から回答へ移動質問文だけで意味を伝える活用法
モーダル風表示href="#modal"対象領域を開く契機本格的なモーダルはARIAも必要role
タブ風UIaria-controlsリンクとパネルを対応選択状態を同期するaria-selected
履歴location.hash現在のフラグメントを取得ページ再訪時の状態を考えるhashchange
URLエンコード%E3%81...日本語IDをURL上で扱う英数字IDのほうが管理しやすいURL
画像リンク<a><img>画像から移動altを空にしない<img>
ボタン風リンクclass="button-link"視覚的に押せる導線リンクとボタンの役割を分ける<button>
新規タブtarget="_blank"外部資料を開くrelを添えるnoopener
アクセシビリティaria-label目的を補足見える文言を優先するARIA
デバッグDevToolsリンク先IDを確認DOM生成後の状態を見るプログラミング
共通部品化component同じ導線を再利用ID重複を避ける設計にするサンプルコード
保守README.mdID命名規則を残す見出し変更時にリンクも直す活用法

アンカーリンクとは何か

アンカーリンクとは、文書内の特定位置や別文書内の特定位置を指すリンクです。URLの末尾に付く#faqのような部分はフラグメント識別子と呼ばれ、ブラウザはその値と一致するidを探してスクロール位置を調整します。

そのため、アンカーリンクは単なる装飾ではなく、情報設計の一部として考えるほうが扱いやすいです。長い解説記事、利用規約、製品仕様、料金表、フォーム付きページでは、読者が途中の内容へ直接入れる構造がプログラミング以前の設計品質を左右します。

アンカーリンクの役割とメリット

これらの役割を整理すると、移動時間の短縮、URL共有のしやすさ、ページ構造の明確化に分かれますが、これは押さえたい点です。たとえばFAQの特定回答へhttps://example.com/help#loginのように案内できると、利用者はページ冒頭から探し直す必要がありません。

一方、アンカーリンクを増やしすぎると、目次やナビゲーションが長くなり、かえって選択しづらくなる場合があるのが目安です。見出し単位のすべてへリンクするより、利用者が移動したい主要セクションを選び、関連が近い項目は本文内の流れで読める形にするのが現実的でしょう。

具体的には、HTMLの構造理解が浅い段階では<div>だけに頼らず、<header><main><section><footer>を使い分けるとよいです。ツリー構造の考え方はHTMLとツリー構造をマスターする!初心者からプロまでわかる7つの完全ガイドと合わせると理解しやすくなります。

アンカーリンクの基本的な使い方

基本的な使い方は、移動先を作ってからリンクを置く順序で考えると迷いにくくなるのがポイントです。移動先にはid属性を付け、リンク側のhrefには同じ文字列を#付きで書く、という対応が中心です。

ただし、idは文書内で一意にする必要があります。同じid="contact"が複数あると、ブラウザやスクリプトがどの要素を対象にするか分かりにくくなり、サンプルコードでは動いて見えても保守時に不具合へつながるかもしれません。

サンプルコード1:ページ内メニューを作る

このサンプルコードは、ページ上部の<nav>から複数の<section>へ移動する最小構成です。リンク文言は移動先の見出しと近い表現にすると、クリック前の期待と移動後の内容がつながりますし、ここがポイントです。

<header id="top">
  <nav aria-label="主要セクション">
    <ul>
      <li><a href="#about">概要</a></li>
      <li><a href="#service">サービス</a></li>
      <li><a href="#contact">お問い合わせ</a></li>
    </ul>
  </nav>
</header>

<main>
  <section id="about">
    <h2>概要</h2>
    <p>サイトの概要を説明するのが一般的です。</p>
  </section>

  <section id="service">
    <h2>サービス</h2>
    <p>提供内容を説明します。</p>
  </section>

  <section id="contact">
    <h2>お問い合わせ</h2>
    <p>連絡方法を説明するのが目安です。</p>
  </section>
</main>

結果: 期待される表示は、上部メニューの「概要」「サービス」「お問い合わせ」を選ぶと、それぞれの<section>へ移動できる状態です。

この構成では、リストの<li>がリンクのまとまりを作り、aria-labelがナビゲーションの目的を補足します。見た目の調整は後からCSSで行えるため、最初にHTMLの対応関係を崩さないことが大切だと言える。

サンプルコード2:CSSでリンクの見た目を整える

そのリンクがクリックできる要素だと分かるように、色、下線、余白、フォーカス状態を整えますし、これが一つの目安です。text-decorationを消すだけではリンクらしさが弱くなるため、:hover:focus-visibleで反応を示すと操作対象として認識しやすくなるのがポイントです。

<style>
  .page-menu {
    display: flex;
    gap: 12px;
    list-style: none;
    padding: 0;
  }

  .page-menu a {
    color: #075985;
    padding: 8px 10px;
    text-decoration: underline;
    border-radius: 4px;
  }

  .page-menu a:hover,
  .page-menu a:focus-visible {
    color: #ffffff;
    background-color: #075985;
    outline: none;
  }
</style>

<ul class="page-menu">
  <li><a href="#about">概要</a></li>
  <li><a href="#service">サービス</a></li>
  <li><a href="#contact">お問い合わせ</a></li>
</ul>

結果: 期待される表示は、リンクにポインターやキーボードフォーカスが当たったとき、背景色と文字色が切り替わる状態です。

一般に、outlineを消す場合は代わりの視覚的なフォーカス表現を用意します。キーボードで移動する利用者にとって、現在どのリンクが選ばれているか分からないUIは操作しづらいためです。

サンプルコード3:固定ヘッダーで見出しが隠れる問題を防ぐ

固定ヘッダーを使うページでは、アンカーリンクで移動した見出しがヘッダーの裏に隠れることがあります。このときは移動先要素にscroll-margin-topを与えると、スクロール停止位置に余白を作れますが、覚えておくと役立つでしょう。

<style>
  .site-header {
    position: sticky;
    top: 0;
    background: #ffffff;
    border-bottom: 1px solid #d1d5db;
  }

  section[id] {
    scroll-margin-top: 72px;
  }
</style>

<header class="site-header">
  <a href="#pricing">料金へ移動</a>
</header>

<section id="pricing">
  <h2>料金</h2>
  <p>料金表を配置します。</p>
</section>

結果: 期待される表示は、「料金へ移動」を選んだときに見出し「料金」が固定ヘッダーに重ならず見える状態です。

この方法はCSSだけで調整できるため、JavaScriptでスクロール位置を細かく計算する前に検討しやすい対策です。ヘッダーの高さが画面幅で変わる場合は、メディアクエリやCSS変数でscroll-margin-topの値を管理すると扱いやすくなります。

サンプルコード4:JavaScriptでクリック時の処理を加える

アンカーリンクはHTMLだけでも動きますが、分析用のログ、表示切替、滑らかな移動などを加える場面ではJavaScriptを併用するのが現実的です。ただし、event.preventDefault()で標準動作を止める場合、移動処理を自分で補う必要があるのが一般的です。

<a href="#details" class="js-scroll-link">詳細へ移動</a>

<section id="details">
  <h2>詳細</h2>
  <p>詳しい説明を配置します。</p>
</section>

<script>
  const link = document.querySelector('.js-scroll-link');

  link.addEventListener('click', (event) => {
    event.preventDefault();

    const target = document.querySelector(link.hash);
    if (!target) return;

    target.scrollIntoView({ behavior: 'smooth', block: 'start' });
  });
</script>

結果: 期待される表示は、「詳細へ移動」を選ぶと#detailsの位置へ滑らかにスクロールする状態です。

ただし、すべての利用者が動きのあるスクロールを好むとは限りません。より丁寧に作るなら、prefers-reduced-motionを確認し、動きを減らす設定の利用者には通常スクロールへ切り替える実装が考えられます。

アンカーリンクの応用例

アンカーリンクの活用法は、目次だけに限られません。FAQ、タブ風UI、アコーディオン、モーダル風の表示、フォーム導線など、同じページ内で文脈を切り替える場面に応用できます。

一方で、本来ボタンであるべき処理をリンクだけで表現すると、支援技術やキーボード操作との整合が崩れる場合があると整理できるのが現実的です。URLの位置を示す役割なら<a>、状態を変える操作なら<button>を選ぶ、という切り分けが基本です。

サンプルコード5:CSSだけでスムーズスクロールを使う

もっとも簡単なスムーズスクロールの使い方は、CSSのscroll-behaviorhtml要素へ設定する方法です。ページ内の多くのアンカーリンクへ同じ挙動を与えたい場合、JavaScriptより短い記述で済みます。

<style>
  html {
    scroll-behavior: smooth;
  }

  @media (prefers-reduced-motion: reduce) {
    html {
      scroll-behavior: auto;
    }
  }
</style>

<a href="#features">特徴へ移動</a>

<section id="features">
  <h2>特徴</h2>
  <p>特徴の説明を配置します。</p>
</section>

結果: 期待される表示は、「特徴へ移動」を選ぶと#featuresへ滑らかに移動し、動きを減らす設定では通常の移動になる状態です。

このようなCSSの扱いは、スライドショーや切り替えUIにもつながりますし、ここを基本と考えるとよいでしょう。視覚的な遷移をHTMLとCSSで組み立てる発想は、HTMLとCSSで手軽に作るスライドショーコピペ12選のようなUI実装にも応用しやすいです。

サンプルコード6:FAQの質問から回答へ移動する

FAQでは、質問一覧を上部に置き、回答それぞれにidを付ける構成が向いています。利用者が知りたい質問だけを選べるため、長い回答群の中から目的の情報を探しやすくなります。

<section aria-labelledby="faq-title">
  <h2 id="faq-title">よくある質問</h2>

  <ul>
    <li><a href="#faq-login">ログインできないときは?</a></li>
    <li><a href="#faq-payment">支払い方法を変更できますか?</a></li>
  </ul>

  <h3 id="faq-login">ログインできないときは?</h3>
  <p>メールアドレスとパスワードを確認すると理解できると整理できます。</p>

  <h3 id="faq-payment">支払い方法を変更できますか?</h3>
  <p>アカウント設定から変更できます。</p>
</section>

結果: 期待される表示は、質問一覧のリンクを選ぶと対応する回答見出しへ移動する状態です。

その構成では、質問文をリンク文言にしておくと、移動先の内容をクリック前に推測できます。単に「詳細」や「こちら」と書くより、リンクだけを拾い読みした場合にも意味が伝わるためです。

サンプルコード7:タブ風UIをアンカーリンクで表す

タブ風UIでは、アンカーリンクのhashを使って対象パネルを切り替えられますし、ここがポイントです。厳密なタブコンポーネントではARIA属性の同期も必要になるため、簡易的な表示切替として理解するとよいでしょう。

<style>
  .panel[hidden] {
    display: none;
  }
</style>

<nav aria-label="商品情報">
  <a href="#panel-basic" class="js-tab-link">基本情報</a>
  <a href="#panel-spec" class="js-tab-link">仕様</a>
</nav>

<section id="panel-basic" class="panel">
  <h2>基本情報</h2>
  <p>商品の概要を配置します。</p>
</section>

<section id="panel-spec" class="panel" hidden>
  <h2>仕様</h2>
  <p>仕様の詳細を配置します。</p>
</section>

<script>
  const tabLinks = document.querySelectorAll('.js-tab-link');
  const panels = document.querySelectorAll('.panel');

  tabLinks.forEach((tabLink) => {
    tabLink.addEventListener('click', (event) => {
      event.preventDefault();
      const target = document.querySelector(tabLink.hash);
      if (!target) return;

      panels.forEach((panel) => {
        panel.hidden = panel !== target;
      });
    });
  });
</script>

結果: 期待される表示は、「基本情報」と「仕様」を選ぶたびに対応する.panelだけが見える状態です。

このサンプルコードではhidden属性で表示状態を管理しています。displayを直接書き換えるより、状態がHTML上にも残るため、後からCSSやテストコードで判定しやすい形になります。

サンプルコード8:フォームへの導線として使う

問い合わせページや採用ページでは、概要説明の途中からフォームへ移動したい場面があると覚えるとよいでしょう。HTMLフォームの設計とアンカーリンクを組み合わせると、説明を読んだ直後に入力欄へ進める導線を作れますが、これは押さえたい点です。

<p>
  申し込み内容を確認したら、
  <a href="#application-form">入力フォームへ移動</a>
  してください。
</p>

<form id="application-form" action="/submit/" method="post">
  <label for="user-name">名前</label>
  <input id="user-name" name="user-name" type="text" autocomplete="name">

  <label for="user-email">メールアドレス</label>
  <input id="user-email" name="user-email" type="email" autocomplete="email">

  <button type="submit">送信</button>
</form>

結果: 期待される表示は、「入力フォームへ移動」を選ぶとid="application-form"のフォーム位置へ移動する状態です。

そのフォーム自体の作り込みでは、<label>fornametype="email"などの対応が読みやすさと入力支援に関わります。フォーム全体の書き方はHTMLで問い合わせフォームを作成する方法5選!も合わせて確認するとよいです。

⚠️ 注意: リンクでフォーム位置へ移動できても、入力値の検証や送信処理が完成するわけではありません。アンカーリンクは移動の仕組みであり、バリデーションはrequiredpattern、サーバー側検証などで別途設計します。

サンプルコード9:ページ上部へ戻るリンク

長いページでは、各セクション末尾に上部へ戻るリンクを置く活用法があると考えられますし、これが一つの目安です。ブラウザのスクロールバーだけに頼らず、本文の流れの中で移動できるため、読み終えた地点から別セクションへ移りやすくなります。

<body id="top">
  <main>
    <section id="chapter-a">
      <h2>章A</h2>
      <p>章Aの本文を配置します。</p>
      <p><a href="#top">ページ上部へ戻る</a></p>
    </section>
  </main>
</body>

結果: 期待される表示は、「ページ上部へ戻る」を選ぶとid="top"を持つ<body>の先頭付近へ移動する状態です。

ただし、ページ上部へ戻るリンクを何度も置く場合は、同じ文言が繰り返されても邪魔にならない位置へ配置すると言えるでしょう。セクションごとの本文末やサイドナビ内など、読書の流れを切りにくい場所が候補です。

サンプルコード10:古いフレーム系ページからの移行時に考えること

古いHTMLでは、フレームや別領域表示を前提にしたページ構成が残っていることがあります。現在のページ設計では、同一ページ内のセクション移動や必要に応じたコンポーネント分割で代替できる場合が多いです。

一方、既存ページを急に作り替えられない場合は、アンカーリンクで主要な位置へ移動できるようにしてから、段階的に構造を見直す進め方もあります。古いフレーム構造の理解にはHTMLにおけるフレームの使い方10選が関連するのが基本です。

よくあるエラーとその対処法

アンカーリンクの不具合は、HTML、CSS、JavaScriptのどこか一部だけを見ても原因が分からないことがあると理解できます。リンク先IDの存在、スクロール位置、クリックイベント、表示状態を順に確認すると、原因を切り分けやすくなります。

リンク先へ移動しない

この症状で最も多い原因は、hrefidの不一致です。href="#contact"なら移動先はid="contact"であり、id="#contact"のように書く必要はありません。

その確認では、ブラウザの開発者ツールで対象要素を検索し、DOM上に該当するidが存在するかを見ると早いです。テンプレートやJavaScriptで後から要素を生成している場合、クリック時点でまだ移動先が存在しない可能性もあるのが目安です。

固定ヘッダーで見出しが隠れる

固定ヘッダーがあるページでは、ブラウザが正しい位置へ移動していても、見出しがヘッダーの下に入り込む場合があります。その場合はscroll-margin-topを移動先要素へ設定し、ヘッダーの高さ分だけ余白を確保します。

ただし、ヘッダーの高さがモバイルとデスクトップで異なる場合、同じ値では片方の表示がずれるかもしれません。@mediaで値を切り替えるか、--header-heightのようなCSS変数にまとめると保守しやすくなるのがポイントです。

リンクの見た目が通常テキストと区別しづらい

リンクにtext-decoration: noneを使い、色の差も小さい場合、利用者はクリック可能な文字列だと判断しづらくなると覚えるとよいでしょう。リンクらしさは下線、色、余白、フォーカス表示の組み合わせで保つのが一般的です。

一方、デザイン上の理由で下線を外す場合でも、:hover:focus-visibleの状態は用意します。マウスだけでなくキーボードで移動する利用者にも、現在の操作位置が伝わる必要があるのが一般的です。

JavaScriptで標準動作を止めている

クリックイベント内でevent.preventDefault()を呼ぶと、ブラウザ標準のページ内移動は止まります。その後にscrollIntoView()などで移動処理を実行していなければ、リンクを選んでも何も起きない状態になると考えられます。

このときは、標準動作を止める理由があるかを見直すのが先です。ログ送信だけなら標準動作を残せる場合があり、表示切替やスムーズスクロールが目的なら、対象要素の存在確認と移動処理をセットで書く必要があるのが現実的です。

URLに日本語IDが入り扱いにくい

HTML上では日本語のidも使えますが、URL上ではエンコードされて長い文字列になることがあります。共有URLやログ解析で扱うなら、id="faq-login"のような英数字とハイフン中心の命名が管理しやすいです。

ただし、既存ページですでに日本語IDが使われている場合、急な変更は外部からのリンク切れを生むかもしれません。移行時は古いIDを残したまま新しいIDへ導くなど、アクセス経路を失わない設計が必要です。

ℹ️ 補足: idの仕様やリンク動作はブラウザが標準化された規則に従って解釈します。HTML属性の詳細はMDNのid属性リファレンスでも確認できると整理できると言えるでしょう。

まとめ

HTMLのアンカーリンクは、hrefidを対応させるだけで始められる一方、長いページの読みやすさやフォーム誘導、FAQの回遊に深く関わります。基本構文を押さえたうえで、CSSのscroll-margin-topやJavaScriptのscrollIntoView()を組み合わせると、実用的な活用法へ広げられます。

その運用で特に押さえたいのは、idの重複を避けること、リンク文言だけで移動先が分かること、固定ヘッダーやキーボード操作への配慮を忘れないことです。サンプルコードをそのまま使う場合でも、ページ構造、見出し、フォーム、ナビゲーションの関係を確認しながら調整すると安定したHTMLになると覚えるとよいでしょう。

アンカーリンクの使い方は、プログラミングの初期学習だけでなく、運用中のWebサイト改善にも役立ちますが、覚えておくと役立つでしょう。本文中の導線、関連記事への移動、問い合わせフォームへの誘導を小さく整えるだけでも、読者が迷いにくいページ構成へ近づけられるでしょう。

関連記事

著者: Japanシーモア編集部

Japanシーモアは、Web/IoT/APP/SYS 分野のプログラミング情報を体系的に提供するメディアです。本記事は編集部による執筆とAI支援を組み合わせて制作し、公開前に編集部が校正しています。誤りや改善案がございましたらお問い合わせよりご連絡ください。

※本記事は実在のエンジニア複数名で構成される Japanシーモア編集部が、AI支援を活用して作成・校正・公開しています。