Cocoonでサイドバー目次を「現在地ハイライト+自動追従」にする方法【長文記事対策】

ブログ運営メモ

Cocoon カスタマイズ

Cocoonでサイドバー目次を「現在地ハイライト+自動追従」にする方法【長文記事対策】

長文記事で「今どこを読んでいるかわからない」という読者のストレスを解消する方法です。サイドバー目次に現在地ハイライトと自動スクロール追従を追加することで、離脱を防ぎ読者体験を大幅に改善できます。エックスサーバー × WordPress × Cocoonの環境で実装した手順をそのまま公開します。

この記事でわかること

  • 現在地ハイライト+自動追従の実装 → 4ステップのコピペ作業で完結
  • CSS追加 → 追加CSSに貼るだけでOK
  • JSの設置場所 → footer.phpの正しい位置に追記

実装するとどうなる?

読んでいるセクションが目次でリアルタイムにハイライトされ、目次が長くても自動でスクロール追従します。

長文記事の読者が感じるストレスの多くは、「今どこを読んでいるのか」「あとどれくらい残っているのか」という現在地の見えなさにあります。
現在地が可視化されると、読者は安心して読み進めやすくなり、離脱率の低下にもつながります。

✅ 実装後に変わること

  • 読んでいるセクションの目次項目がハイライト表示される
  • 目次が長い場合、アクティブ項目が常に表示範囲内に入るよう自動追従する
  • 読者が「今どこにいるか」を常に把握できる

実装はコードのコピペが中心です。難しい作業はありませんが、テーマファイルを編集するため、必ず事前にバックアップを取ってから進めてください。

手順の全体像(ざっくり)

作業は4ステップ。コードはすべてコピペで完結します。

📋 全体手順

  1. サイドバーに目次ウィジェットを設置
  2. 追加CSSを設定する
  3. Cocoon本体のfooter.phpを子テーマへコピー
  4. footer.phpにJSを追加する

それでは各ステップを詳しく解説します。

① サイドバーに目次を追加する

WordPress管理画面の「外観 → ウィジェット」から、目次ウィジェットをサイドバーに追加します。

「サイドバースクロール追従」エリアに目次ウィジェットを追加してください。

サイドバーに目次ウィジェットを追加する画面

注意:Cocoonの大元設定と目次の表示深さを揃えてください。たとえば大元でh3まで表示する設定にしているのに、ウィジェット側でh2までにするとミスマッチが起き、ハイライトが正しく動作しません。

② 追加CSSを設定する

WordPress管理画面の「外観 → カスタマイズ → 追加CSS」に以下のコードを貼り付けます。

追加CSSの設定画面

目次が長い場合もスクロールできるようにするCSSです。アクティブ項目は青い左ボーダーとハイライト背景で強調されます。

#sidebar-scroll .widget.widget_toc .toc-content{
  max-height: 55vh;
  overflow: auto;
}
#sidebar-scroll .widget.widget_toc a{
  display: block;
  padding: 6px 0 6px 12px;
  text-decoration: none;
  border-left: 3px solid transparent;
  transition: background .2s ease, border-color .2s ease;
}
#sidebar-scroll .widget.widget_toc a.is-active{
  background: rgba(59,130,246,0.12);
  border-left: 3px solid #3b82f6;
  font-weight: 600;
}

結論:CSSはここまでで完結です。見た目の調整はこのコードだけで対応できます。

③ Cocoon本体のfooter.phpを子テーマへコピーする

子テーマ側にfooter.phpがない場合は、Cocoon本体からコピーして追加します。

テーマ本体を直接編集するとアップデート時に上書きされます。必ず子テーマに追加してください。

注意:すでに子テーマ側にfooter.phpがある場合、またはJSを追記できるファイルがある場合はこの手順をスキップして④へ進んでください。

⚙️ エックスサーバーでの作業手順

エックスサーバーのファイルマネージャ画面
  1. エックスサーバーにログインしてサーバーパネルを開く
  2. ファイルマネージャから該当ドメインを開く
  3. /public_html/wp-content/themes/cocoon-master/footer.php をコピー
  4. /public_html/wp-content/themes/cocoon-child-master/footer.php として貼り付け

④ footer.phpにJSを追加する

WordPress管理画面の「外観 → テーマファイルエディター → Theme Footer(footer.php)」を開き、</div><!-- #container -->の直前に以下のJSコードを追加します。

footer.phpへのJS追記位置

追加するJSコード

<script>
document.addEventListener("DOMContentLoaded", () => {
  const toc = document.querySelector("#sidebar-scroll .widget.widget_toc");
  if (!toc) return;

  const tocScroll = toc.querySelector(".toc-content") || toc;
  const links = Array.from(toc.querySelectorAll('a[href^="#"]'))
    .filter(a => a.getAttribute("href").length > 1);

  const items = links.map(a => {
    const id = decodeURIComponent(a.getAttribute("href").slice(1));
    const el = document.getElementById(id);
    return el ? { id, el, a } : null;
  }).filter(Boolean);

  if (!items.length) return;

  const OFFSET = 160;
  let currentId = null;

  function clearActive(){
    links.forEach(a => a.classList.remove("is-active"));
  }

  function keepActiveVisible(activeLink){
    if (tocScroll.scrollHeight <= tocScroll.clientHeight) return;
    const cRect = tocScroll.getBoundingClientRect();
    const aRect = activeLink.getBoundingClientRect();
    const padding = 14;
    if (aRect.top < cRect.top + padding ||
        aRect.bottom > cRect.bottom - padding) {
      activeLink.scrollIntoView({
        block: "center",
        inline: "nearest",
        behavior: "smooth"
      });
    }
  }

  function setActive(id){
    if (id === currentId) return;
    currentId = id;
    clearActive();
    const hit = items.find(x => x.id === id);
    if (!hit) return;
    hit.a.classList.add("is-active");
    keepActiveVisible(hit.a);
  }

  function update(){
    let candidate = items[0];
    for (const it of items) {
      const top = it.el.getBoundingClientRect().top;
      if (top <= OFFSET) candidate = it;
      else break;
    }
    setActive(candidate.id);
  }

  let ticking = false;
  function onScroll(){
    if (ticking) return;
    ticking = true;
    requestAnimationFrame(() => {
      update();
      ticking = false;
    });
  }

  window.addEventListener("scroll", onScroll, { passive: true });
  window.addEventListener("resize", onScroll, { passive: true });
  window.addEventListener("load", onScroll);
  update();
});
</script>

固定ヘッダーがある場合の調整

固定ヘッダーがある環境では、本文の表示タイミングとハイライトのタイミングがずれることがあります。その場合は以下の数値を調整してください。一般的な固定ヘッダーなら240前後が目安です。

const OFFSET = 160;

結論:ここまでで実装は完了です。ページを読み込んでスクロールし、目次のハイライトが動いていれば成功です。

なぜこの実装が重要なのか?

長文記事で離脱が増える最大の原因は「現在地が見えないこと」です。それを解消するのがこの実装です。

5,000〜1万文字の記事は情報量で価値を出せますが、読者にとっては読むこと自体が負荷です。
「今どこにいるかわからない」「終わりが見えない」というストレスが重なると、離脱率は確実に上がります。

現在地が可視化されると以下の変化が起きます。

📈 期待できる効果

  • 読者が安心して読み進められる
  • 「あとこれだけ」が見えることで読了率が上がる
  • 離脱が減り、UX向上がSEOにも好影響をもたらす

長文コンテンツを書くブログほど、この改善の効果は大きくなります。

よくある質問

Q 子テーマがない場合はどうすればいいですか?

子テーマなしにCocoon本体のfooter.phpを直接編集すると、テーマアップデート時に変更内容が上書きされます。必ずCocoon Child(子テーマ)を有効化してから作業してください。子テーマはCocoon公式サイトで配布されています。

Q ハイライトが動作しない場合の確認ポイントは?

最も多い原因はCocoon大元設定とウィジェットの目次表示深さのミスマッチです。たとえば大元でh3まで表示している場合は、ウィジェット側も同じ設定にしてください。また、JSがfooter.phpの正しい位置(</div><!-- #container -->の直前)に追記されているかも確認してください。

Q 固定ヘッダーがある場合の調整方法は?

JSコード内のconst OFFSET = 160;の数値を変更してください。固定ヘッダーの高さに合わせて200〜240程度に増やすと、ハイライトのタイミングが本文表示と合いやすくなります。

Q Cocoon以外のテーマでも使えますか?

JSとCSSはCocoon専用のクラス名(widget_tocなど)を参照しているため、他テーマでは目次ウィジェットのHTML構造に合わせてセレクタを書き換える必要があります。汎用性はありますが、そのままのコピペでは動作しない場合があります。

まとめ|4ステップで「現在地が見える目次」を実装できる

今回やったことは4つです。ウィジェットの設置、CSS追加、footer.phpの子テーマへのコピー、JSの追記。コードはすべてコピペで完結するため、初心者でも作業できます。

最終結論:

長文記事を書くブログほど、この改善の効果は大きい。
読者の「今どこ?」を解消するのが、離脱対策の第一歩です。

なお、この記事はエックスサーバー上での手順を前提にしています。サーバーパネルの操作に慣れていない方は、先にパネルの全体像を把握しておくとスムーズです。

エックスサーバーはWordPressとの相性が良く、ファイルマネージャも使いやすい国内人気No.1のレンタルサーバーです。今ならキャンペーン中につき通常より割引で始められます。

エックスサーバーの公式サイトを見る

コメント

タイトルとURLをコピーしました