нуль

Web技術を
知る・試す・楽しむ
ためのテックブログ

ブログ

Astroのブログに目次機能をつける

投稿日:

はじめに

Astroで作成したこのブログに目次機能を実装したのでやり方を書く。
画面幅960px以上で閲覧すると記事の左側に目次リンクが表示されます📔

結論としてはTocBotというライブラリーを利用して簡単に実装することができた。

Tocbot
Tocbot - Generate a table of contents based on the heading structure of an html document
Tocbot favicon tscanlin.github.io

前提として

AstroではMarkdownで書いた見出しに対して自動でidが振られます。
また、Astroのrender()メソッドの戻り値で見出しのリストが返ってきます。

---
import { getEntryBySlug } from 'astro:content';
const entry = await getEntryBySlug('blog', 'entry-1');
 
const { Content, headings } = await entry.render();
---

上記のようにconst { Content, headings } = await entry.render();headingsに見出しのリストが返ってきます。

👇ドキュメント

Astro Runtime API
Astro Runtime API favicon docs.astro.build
Astro Runtime API

このように目次の情報が取得できるので、コンポーネントを作るなりで自由に作ればいいのだが、スクロール位置によって目次リンクをアクティブにするなどを自作するのは大変だったのでライブラリーに頼った。

TocBotの使い方

そこでライブラリーとしてTocBotを採用しました。
TocBotはフレームワーク非依存なJavaScriptライブラリーで、セレクターで指定した要素の中を走査して、見つかった見出しからリンクを含むリスト要素を生成してくれます。また、スクロール位置によって目次にアクティブクラスを自動で付与してくれます。

⬇️は当ブログのtableOfContents.astroコンポーネントになります。
(長いのでCSSは省略してます。)

tableOfContents.astro
---
 
---
<nav class="toc-nav">
  <div class="toc-title">
    <h2>目次</h2>
  </div>
  <div class="toc"></div>
</nav>
 
<script>
  import * as tocbot from 'tocbot'
 
  tocbot.init({
    tocSelector: '.toc', // 目次を追加するクラス名
    contentSelector: '#article-body', // 目次を取得するコンテンツ
    activeLinkClass: 'to-link-active', // アクティブになった時のクラス名
    listClass: 'toc-list', // olのクラス名
    linkClass: 'toc-link', // aタグのクラス名
    headingSelector: 'h2, h3' // 目次として取得する見出しタグ
  })
</script>

Important

Astroでコンポーネント内でCSSを書く場合、CSSにはis:globalを付ける必要があります

まとめ

TocBotライブラリーを使ってブログに目次機能を付けました。
非常にお手軽にスクロール位置の指定などの機能を付けられ便利でした。