当ページのリンクには一部広告が含まれています。
うさねこ気まぐれPG開発室

【WordPress対応】Cocoon対応 サイドバー目次を追従させるJavaScript+CSSサンプル コピペだけで導入OK

広告

【WordPress対応】Cocoon対応 サイドバー目次を追従

ねこちゃん
ねこちゃん

ねえ、うさちゃん?
いつから、うさねこ散歩のブログPC版は、スクロールすると右の目次がふわっと動くようになったの?

うさちゃん
うさちゃん

うん、あれね、“スクロール追従目次”っていうの~。読者の方が迷わないように、ナチュラルで優しい動きを意識して作ってみたよ✨️

ねこちゃん
ねこちゃん

確かに、わかりやすいわね。うさちゃんのドヤ顔も見えるようだわ。

うさちゃん
うさちゃん

まあね!ドヤァ!

スクロール追従する目次(ふんわりハイライト版)

うさちゃん
うさちゃん

「Cocoonテーマをもっとやさしく、心地よく」をコンセプトにしたカスタムシリーズ。

今回紹介する「スクロール追従する目次(ふんわりハイライト版)」を元にした改造版を実際にうさねこ散歩サイトの全記事で使用しています🐰🐱💫

動作サンプル画面

これでできること

  • 目次がスクロールに合わせて追従
  • 読んでいる見出しがやさしくハイライト
  • Cocoon標準の目次構造(#toc-2)にそのまま対応
  • PC専用(スマホでは自動無効)
  • 軽量・高速(40ms更新で滑らか)

設置手順(Cocoon専用)

ステップ①:ウィジェットに設置

うさちゃん
うさちゃん

“目次をサイドバーに固定したい人” は、Cocoonウィジェットを使います。

手順

  1. 「外観 → ウィジェット」 を開く
  2. サイドバー領域(例:サイドバー(投稿ページ))を選択
  3. 目次(CocoonのTOCウィジェット)」を追加
  4. タイトル欄に「📖 目次」など好きな名前を入力してもOK
    サンプル画面ではプログラム表示と2重表示になるので入力していません。
  5. 保存して完了!

ステップ②:スクリプトを追加

  1. WordPressの管理画面 → 外観 → テーマファイルエディター
  2. 右側で「Cocoon Child(子テーマ)」を選択
  3. javascript.js を開く
  4. 一番下に以下を貼り付けて保存
// =====================================================
// サイドバー目次追従スクリプト(滑らか版)
// -----------------------------------------------------
// 目的
//   - サイドバー目次(#toc-2)を、スクロール位置に応じて自動でハイライト
//   - 「今読んでいる章」をふんわり強調表示してユーザー体験を向上
// 特徴
//   - PC専用(スマホでは無効)
//   - Cocoonの目次構造(#toc-2 li a)に完全対応
//   - スムーズかつ軽量なスクロール監視(40ms間隔)
//   - ページリサイズやトグル開閉にも自動再計算対応
// =====================================================

// -----------------------------------------------------
// 1. モバイル判定
// -----------------------------------------------------
//   → スマホやタブレットでは、Cocoon標準で目次が折りたたまれることが多いので
//      PC表示のみに限定して動作させる。
if (!/iPhone|Android.+Mobile/.test(navigator.userAgent)) {

  // jQuery準備完了後に実行
  jQuery(function ($) {

    // -------------------------------------------------
    // 2. 主要変数
    // -------------------------------------------------
    const headerLinks = $('#toc-2 li a'); // 目次リンク(各h2/h3へのアンカー)
    let contentsPos = [];                  // 各見出しのスクロール位置情報を保持する配列

    // -------------------------------------------------
    // 🪄 3. 初期化関数:見出しの位置を取得して保存
    // -------------------------------------------------
    function init() {
      contentsPos = []; // リセット(リサイズ時など再計算用)

      headerLinks.each(function (i) {
        const id = $(this).attr('href'); // 例: "#section1"
        const $target = $(id);
        if (!$target.length) return; // 対応する見出しが存在しない場合はスキップ

        // 見出しの上端座標を取得(30px上に余裕を取る)
        const top = $target.offset().top - 30;
        contentsPos[i] = { top, bottom: null };

        // 1つ前の「bottom」(範囲の終端)を現在のtopで決定
        if (i > 0) contentsPos[i - 1].bottom = top;
      });

      // ページ最下部(footer手前)でハイライトが消えるように最終範囲を補正
      const $footer = $('footer');
      if ($footer.length && contentsPos.length) {
        const footerTop = $footer.offset().top - 30;
        contentsPos[contentsPos.length - 1].bottom = footerTop;
      }
    }

    // -------------------------------------------------
    // 4. 現在位置チェック関数
    // -------------------------------------------------
    // スクロール位置(scrollTop)を取得して、
    // どの見出し範囲に入っているかを調べる。
    function currentCheck() {
      const scrollTop = $(window).scrollTop();
      headerLinks.parent().removeClass('current'); // 一旦リセット

      if (!contentsPos.length) return; // 範囲情報がなければ処理しない

      // スクロール位置が最初〜最後の範囲内にあるときのみ処理
      if (
        scrollTop >= contentsPos[0].top &&
        scrollTop < contentsPos[contentsPos.length - 1].bottom
      ) {
        // 現在の位置がどの見出し範囲に属するかを探索
        for (let i = 0; i < contentsPos.length; i++) {
          const c = contentsPos[i];
          if (scrollTop >= c.top && scrollTop < c.bottom) {
            // 一致する範囲が見つかったら、その項目にcurrentを付与
            headerLinks.eq(i).parent().addClass('current');
            break;
          }
        }
      }
    }

    // -------------------------------------------------
    // 5. イベント設定
    // -------------------------------------------------
    // ページ読込・リサイズ時に位置を再計算
    $(window).on('load resize', init);

    // スクロールイベント監視(軽量化+滑らか更新)
    let scrollTimer = null;
    $(window).on('scroll', function () {
      if (scrollTimer) return; // 二重呼び出し防止
      scrollTimer = setTimeout(() => {
        currentCheck();
        scrollTimer = null;
      }, 40); // ← 更新間隔:40ms(約1/25秒)
    });

    // -------------------------------------------------
    // 6. Cocoonのトグル対応
    // -------------------------------------------------
    // Cocoonでは、目次を「開閉できるトグル構造」で出力するため、
    // 開閉後にDOMの位置が変化する。→ 再計算を500ms後に実行。
    $(document).on('change', 'input.toggle-checkbox, input.toc-checkbox', function () {
      setTimeout(init, 500);
    });

  });

}
  • Cocoon Childのjavascript.jsは自動で読み込まれるので、別途 enqueue(登録処理)を書く必要はありません。
  • ファイル保存後は、ブラウザキャッシュをクリアして確認を。
  • 他のスクリプト(例:目次トグルやjQueryプラグイン)がある場合は、ファイルの最後に追加するのが安全です。

ステップ③:CSSを追加

次に、外観 → カスタマイズ → 追加CSS に以下を貼り付けます。

/* ==========================================
TOC – Natural Flat Card Edition(Wide Harmony Version)
------------------------------------------
- 外枠の幅を本文いっぱいに近づける
- 内部タイトルと背景を一体化
- hoverやcurrentの演出は自然で柔らかく
========================================== */

/* ----------------------------------------------------
 1. 目次全体(Cocoonの外枠 .toc)
---------------------------------------------------- */
.toc {
  background: linear-gradient(180deg, #fffdf8 0%, #fffaf0 100%);
  /* 淡いオフホワイト~ベージュのグラデーション背景 */
  border: 1px solid #f2e9d9;
  /* 枠線を柔らかいベージュに */
  border-radius: 12px;
  /* カードの角を丸く */
  padding: 1.8em 2em;
  /* 内側余白をやや広めに(タイトルや番号が詰まらない) */
  box-shadow: 0 3px 14px rgba(180, 160, 120, 0.12);
  /* 柔らかい立体感の影 */
  font-family: "Noto Sans JP", "Yu Gothic", sans-serif;
  transition: all 0.35s ease;
  max-width: 100% !important;
  /* 幅制限を解除して本文幅に合わせる */
  width: 100%;
  box-sizing: border-box;
}

/* hover時にほんの少し浮かす */
.toc:hover {
  box-shadow: 0 6px 22px rgba(180, 160, 120, 0.18);
  transform: translateY(-2px);
}

/* ----------------------------------------------------
2. 内部タイトル(例:📘 目次)
---------------------------------------------------- */
#toc-2 .toc-title {
  background: linear-gradient(135deg, #f8f9fa 0%, #fffaf3 100%);
  /* Cocoon標準 #f8f9fa に寄せた柔らかい白グレー基調 */
  color: #3c3a36;
  font-weight: 700;
  font-size: 1.1em;
  padding: 0.8em 1.2em;
  border-radius: 10px;
  margin-bottom: 1em;
  display: flex;
  align-items: center;
  gap: 0.5em;
  letter-spacing: 0.04em;
  box-shadow:
    inset 0 0 4px rgba(255, 255, 255, 0.8),
    0 1px 5px rgba(200, 180, 140, 0.12);
  border-left: 5px solid #d7b97f;
  /* 見出しらしいアクセントライン */
  transition: all 0.35s ease;
  width: 100%;
  /* タイトルもブロック全体に広げる */
}

/* 📘 アイコン装飾 */
#toc-2 .toc-title::before {
  content: "📘";
  font-size: 1.1em;
  opacity: 0.9;
}

/* hover時 */
#toc-2 .toc-title:hover {
  background: linear-gradient(135deg, #fffdf7 0%, #fff4e6 100%);
  border-left-color: #cfa95c;
  box-shadow:
    0 3px 10px rgba(200, 180, 140, 0.25),
    inset 0 0 6px rgba(255, 255, 255, 0.9);
  transform: translateY(-2px);
}

/* ----------------------------------------------------
3. リスト全体の整形
---------------------------------------------------- */
#toc-2 ul {
  margin: 0;
  padding-left: 1.6em;
  /* 階層を少しインデント広めに(見やすく) */
  list-style: decimal;
  line-height: 1.8;
  /* 行間を少し広げて読みやすく */
}

/* ----------------------------------------------------
4. 各目次項目(li)
---------------------------------------------------- */
#toc-2 li {
  margin: 0.25em 0;
  padding: 0.45em 0.7em;
  border-radius: 6px;
  transition:
    background-color 0.4s ease,
    transform 0.4s ease,
    box-shadow 0.4s ease;
}

/* ----------------------------------------------------
5. current(現在位置)項目の強調
---------------------------------------------------- */
#toc-2 li.current {
  background: linear-gradient(135deg, #fffaf0 0%, #f8eedc 100%);
  box-shadow:
    inset 0 0 5px rgba(255, 255, 255, 0.7),
    0 0 8px rgba(210, 190, 150, 0.2);
  border-left: 3px solid #d7b97f;
  transform: translateY(-2px);
}

/* hover時(やや浮かせて発光) */
#toc-2 li.current:hover {
  transform: translateY(-4px);
  background: linear-gradient(135deg, #fff8ed 0%, #f4e7cc 100%);
  box-shadow:
    0 4px 12px rgba(200, 180, 130, 0.35),
    inset 0 0 8px rgba(255, 255, 255, 0.8);
}

/* ----------------------------------------------------
6. 子階層リスト(H3など)
---------------------------------------------------- */
#toc-2 li.current li {
  background-color: rgba(255, 253, 248, 0.8);
  border-radius: 8px;
  padding-left: 1em;
  margin: 3px 0;
}

/* ----------------------------------------------------
7. リンク文字の装飾
---------------------------------------------------- */
#toc-2 li.current a {
  color: #6c5733 !important;
  font-weight: 600;
  text-decoration: none;
}
#toc-2 li.current a:hover {
  color: #8a6a3f !important;
  text-shadow: 0 0 4px rgba(140, 110, 60, 0.25);
}

/* ----------------------------------------------------
8. マーカー(項目前のドット)
---------------------------------------------------- */
#toc-2 li::before {
  content: "•";
  color: #c9b88f;
  margin-right: 6px;
  font-size: 0.9em;
  vertical-align: middle;
}
#toc-2 li.current::before {
  color: #d7b97f;
}
  • CocoonはCSSの読み込み順に注意:既存のCSSとの競合にも注意しすること。
  • 既存のCSSがある場合は上書きされる可能性あり:同じセレクタなら後から書いた方が優先される。
  • 反映されないときはキャッシュ削除+スーパーリロード(Ctrl+F5)
  • 目次は#toc-2が対象:本文用.tocとは別なので混同しないように。

まとめ

  • Cocoonにコピペだけで導入OK
  • PCでのみ動作(スマホは完全に無効化)
  • ウィジェットを使えばサイドバー固定も簡単
  • 実際にうさねこ散歩サイトでも使用中!

WordPress+Cocoonを始めるなら「エックスサーバー」がおすすめ!

「これからWordPress+Cocoonでブログを作りたい!」という方には、
国内シェアNo.1の高速レンタルサーバー エックスサーバーがぴったりです。

  • 🚀 WordPressクイックスタート対応(最短10分でブログ開設)
  • 🪄 Cocoonテーマの自動インストールにも対応
  • 🔒 無料独自SSL/高セキュリティ/自動バックアップ完備
  • ☁️ 高速SSD・安定稼働率99.99%以上
  • 💰️ スタンダード 月額料金 990円~  693円~(キャンペーン中なら) 2025/11現在

「WordPress × Cocoon」を最もスムーズに始められる環境が整っています。
👉 今すぐチェック:レンタルサーバー エックスサーバー

免責事項

本記事のサンプルプログラムは実行を保証するものではなく、利用に伴う結果について一切の責任を負いません。

広告