MENU

Next.jsで作った自作ブログに目次機能を追加【tocbot】

【過去に書いたブログ記事のリライト版です】

この記事では、Next.jsとmicroCMSで作ったブログにTocbotを用いて、目次機能を追加する場合の導入方法について解説していきます。

目次

Tocbotとは?

まずは、Tocbotについて簡単に紹介します。

指定したHTMLの要素に含まれる見出しタグ(h1、h2、h3など)を抽出し、それらを自動的に目次として作成することができる便利なライブラリになります。

【Tocbotの公式サイト】

使い方について

ここからは、tocbotの実際の使い方を書いていきます。

tocbotのインストール

以下のコマンドを利用し、Tocbotをインストールします。

npm install --save tocbot

CDNを利用する場合は以下の内容をbodyタグの終了タグの直前に記載します(公式サイトより)。

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.min.js"></script>

目次を作る

ReactのuseEffectでTocbotを初期化します。

HTMLがレンダリングされた後で、その反映された内容に対して動作させるため、useEffectを使用します。

import tocbot from 'tocbot'

useEffect (() => {
  tocbot.init({
    tocSelector: '.toc',
    contentSelector: '.post',
    headingSelector: 'h2, h3, h4',
    // headingSelectorはどこまで目次に含むかで変えてください
})

return () => tocbot.destroy() 
// destroy関数を使用し、不要となったtocbotインスタンスを削除します
}, [])

※各Selectorの説明

tocSelector
 目次をどこに表示させるかについて、その表示先となるタグに付与されているクラス名を指定(ここでは「toc」というクラス名が付与されているdivタグなどに目次を生成することを意図しています)

contentSelector
 目次を抽出する元ネタになる要素を判断するためのクラス名を指定します。
 ここでは、bodyタグなどに「post」というクラス名を付与し、このbodyタグの中の要素から目次を生成するフラグを立てます。

headingSelector
 contentSelectorで選択した親要素から、目次の要素となる項目を抽出するため、その抽出対象とするタグ名を記載していきます。
 ここでは「h2」タグから「h4」タグまでを目次の要素として取り扱うフラグを立てました。

全体的なコード

最終的なToc.tsx(component)は下記の様な内容となりました。

import React, { useEffect } from 'react';
import tocbot from 'tocbot'

const Toc = () => {
  useEffect(() => {
    tocbot.init({
      tocSelector: '.toc',
      contentSelector: '.post',
      headingSelector: 'h2, h3, h4',
    });
    return () => tocbot.destroy()
  }, []);


  return (
    <div className="p-4 m-2 border-2">
      <h3 className="text-center p-2 mb-1 font-semibold border-b">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="inline text-teal-400 ai ai-Book"><path d="M2 6s1.5-2 5-2 5 2 5 2v14s-1.5-1-5-1-5 1-5 1V6z"/><path d="M12 6s1.5-2 5-2 5 2 5 2v14s-1.5-1-5-1-5 1-5 1V6z"/></svg>
        この記事の目次
      </h3>
      <div className='toc mt-1 mb-1'></div>
      <style jsx global>{`
        .toc {
          border-radius: 0.25rem;
          padding: 1rem;
          font-size: 1rem;
        }

        .toc-list .toc-list {
          padding-left: 1rem;
          padding-top: 0.5rem;
        }

        .toc-list-item {
          padding-bottom: 0.5rem;
        }

        .toc-list-item:last-child {
          padding-bottom: 0;
        }

        .toc-link {
          color: rgba(156, 163, 175, 0.7);
        }

        .is-active-link {
          color: #282828;
          font-weight: 700;
        }
      `}</style>
    </div>
  );
};

export default Toc;

スタイルは外部のCSSモジュールにより読み込んでもいいですし、上記のように目次用にcss-in-JSで書いても良いと思います。

ただし、外部モジュールを読み込む場合は、各要素に個別にスタイルを適用することは難しい(microCMSから読み込んだDBからHTMLを生成する)ため、scssによりCSSを書き、一つのクラス名ですべてのスタイルを読み込み、一括適用する必要があると思います。

また、私の場合は、記事の本文にhilight.jsを適用する都合があったため、外部cssファイルを作成し、スタイルを適用することができませんでした(私の技術力不足、勉強不足だと思います)。

そのため、上記のようにcss-in-JSの形でスタイルを適用することとしました。

完成形は?

自分で一から目次を作る場合、作業自体が結構難しいと思い、調べるうちにこのtocbotを見つけました。

このライブラリを導入するだけで、簡単に目次が生成されるため、ぜひ自作ブログをお考えの方は、導入してみてください。

それでは今回は以上となります。

最後まで読んでいただきありがとうございました。

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

はじめまして、ふじです。
Python、Django、FastAPI、React.js、Next.jsを学習している、ずっと文系のプログラミング独学者です。

目次