革命学舎

太陽のアイコン 月のアイコン
ブログトップ画像
革命学舎
書く、これしか出来ないから。

Astroサイトに目次をつける

投稿日: 2025-11-03

タグ: # tech , # blog

前回の記事から、記事に目次をつけるようにした。自由に書いているときなら必要ないかもしれないが、この記事のようなまじめなものにはついているほうが「それっぽい」と思う。今回は、Astroで構築したブログに折りたたみ可能な目次を実装する方法についてだ。

目次

目次

必要なパッケージ

まずは必要なパッケージをインストールする。以下の三つが必要。


設定方法

次にこれらの設定をastro.config.mjsに書く。私のものは以下の通り。

astro.config.mjs
import remarkToc from 'remark-toc';
import remarkCollapse from 'remark-collapse';
import rehypeSlug from 'rehype-slug';
export default defineConfig({
markdown: {
gfm: false,
remarkPlugins: [
remarkGfm,
remarkAttributes,
[remarkToc, {
heading: "目次|Contents",
maxDepth: 4
}],
[remarkCollapse, {
test: "目次|Contents",
summary: "目次",
}]
],
rehypePlugins: [
rehypeSlug
],
}
// ほかの設定は省略
});

スタイルの装飾

表示の問題

さて、これで記事を以下のように書いてみる。

### 目次
### 小見出し1
#### 項目1
aaa
#### 項目2
bbb
### 小見出し2
ccc

するとおそらくこのように表示される。 「目次」という見出しの下にdetails要素のsummaryである「目次」の字が来ている画像 「目次」の言葉は二つはいらない。後から生成されるsummaryのほうだけ残して、remark-tocのために入れてある### 目次の部分を見えなくしたい。常に「目次」の言葉を使うなら#目次のCSSを書けばいいが、言葉が変わればidは変わってしまう。目次が一番前になることが確約されているなら、記事の中のhタグから:first-childdisplay: noneにすればいいが、自分はremark-attributesを入れているのでこのようにも書ける。

### 目次{: .toc-heading}

これでこの要素にtoc-headingクラスをつけることができ、このクラスにdisplay: noneをつけている。

CSSの実装例

自分のCSSはこんな感じ

/* 見出しの装飾 */
.prose .toc-heading {
display: none;
}
.prose details {
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
cursor: pointer;
}
.prose details a {
color: #0066cc;
}
.prose h3, .prose h4 {
position: relative;
width: fit-content;
margin: .7rem 0;
}
.prose h3 {
font-size: 1.2rem;
font-weight: 700;
padding: 0 .5rem 0 1.2rem;
border-bottom: 2px solid #ff7f7e;
}
.prose h3::before {
content: '#';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: #ff7f7e;
}
.prose h4 {
font-size: 1rem;
font-weight: 600;
padding: 0 .5rem 0 1rem;
}
.prose h4::before {
content: '・';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: #ff7f7e;
}

details要素はユーザーがクリックするところなので、テキストを選択できないようにし、cursor: pointerを設定している。
h3h4の見出しには、::beforeを使って装飾を追加している(これほんと便利)。h3には#h4にはを先頭に表示し、h3には下線をつけることで階層の違いが分かりやすくなっていると思う。それぞれのpaddingがややこしいことになっているのは左に#のためのスペースを空けるため。

参考