Published on

WordPressで目次を作成してサイドバーに固定する方法【プラグインなし】

目次

記事をスクロールしても横に目次が固定されるやつです。

プラグインを使わず目次を作成してスクロールしても目次をサイドバーに固定してみます。

興味のあるかたは使ってみてください。

完成した見た目

確認に使ったテーマはTWENTYSIXTEENです。

目次のスクリプト

footer.phpのbody直前に追記します。

...省略

<!-- ここから目次作成スクリプト -->

<script>
const indexWrap = document.querySelector('.index_wrap');  //H2タグの前に挿入したdivタグ
if ( indexWrap ) {

    let postContent = document.querySelector('.entry-content');  //記事本文が書かれているラッパー
    let hTags = postContent.querySelectorAll('h2, h3');         //記事内のH2とH3タグを全て取得

    if (hTags.length > 0) {
        let indexList = document.createElement("ul");
        let listSrc = "";
        let h3List = "";    //h3タグを取得しておくための変数
        for (let i = 0; i < hTags.length; i++) {
            let theHeading = hTags[i];
            theHeading.setAttribute('id', "index_id" + i);  //リンクで飛べるようにIDをつける
            if (theHeading.tagName === 'H2') {
                if (h3List !== "") {
                    //h3リストが生成されていれば
                    listSrc += '<ul>' + h3List + '</ul>';
                    h3List = "";
                } 
                listSrc += '</li><li><a href="#index_id' + i + '">' + theHeading.textContent + '</a>';
            } else if (theHeading.tagName === 'H3') {
                h3List += '<li><a href="#index_id' + i + '">' + theHeading.textContent + '</a></li>';
            }
        }
        if (h3List !== "") {
            //最後のリストがh3だった場合
            listSrc += '<ul>' + h3List + '</ul></li>';
        } else {
            listSrc += '</li>';
        }
        indexList.innerHTML = listSrc;
        indexWrap.appendChild(indexList);
    }
}
</script>
<!-- ここまで目次作成スクリプト -->


</body>
</html>

参考サイトhttps://wemo.tech/67

コピペで大丈夫なんですが、本文を囲っている場所のクラス名なんかはテーマによって違ったりするので各自で確認しましょう。

let postContent = document.querySelector('.entry-content'); 

この場合は.entry-contentですが、enrty_contentだったりentry_postだったりテーマによって違いがあります。
ここが合ってないと動作しません。

これで目次を作成する用意ができまして、次に目次を表示させます。

position stickyでスクロールしてもサイドに固定する

サイドバーに表示するのですがスクロール量を計算してーとか面倒なことせず簡単な方法がありました。

cssで目次にposition: sticky;を使えば固定できるようです。

ただ少し罠がありまして、ここまでくると通常はウィジェットに目次を表示するためのタグ(コード)をおいて終わりかと思ったのですが違いました。

どうやら入れ子の状態だとうまく固定されないようです。

なのでウィジェットではなくsidebar.phpなどのサイドバーのファイルに直接かきます。

//sidebar.php

<?php if ( is_active_sidebar( 'sidebar-1' ) ) : ?>
	<aside id="secondary" class="sidebar widget-area" role="complementary">
		<?php dynamic_sidebar( 'sidebar-1' ); ?>
	</aside><!-- .sidebar .widget-area -->
     //ここ目次用の追加タグ
	<div class="index_wrap sticky"><span>目次</span></div>
     //ここまで目次用の追加タグ
<?php endif; ?>

ここでも注意ですが、 aside の中に入れる形だと入れ子になりうまく固定されません。
なので外にだしましょう。

これだけだとサイドバーのCSSが効かないので、サイドバー用のCSSを効かせます。

//cssの例

.sticky {
  position: -webkit-sticky;
  position: sticky;
  /* ここからテーマに合わせて変更してください  */
  top: 10px;
  float: left;
  margin-left: 75%;
  padding: 0;
  width: 25%;
}

/* 目次というテキストのみためを変える場合の例*/
.index_wrap{
font-size:1.3rem;
padding:10px;
}

スマホで目次を非表示にする場合

@media screen and (max-width: 480px) {
 .index_wrap{
 display:none;
 }
}

ざっと説明しましたが、クラス名が干渉したりするとデザインが崩れるのでご注意を。好きなように変更してください。