Skip to content

見出し階層をヘッダー直下のパンくずバーで表示 - #187

Open
riiimparm wants to merge 13 commits into
developfrom
feature/heading-breadcrumb-bar
Open

見出し階層をヘッダー直下のパンくずバーで表示#187
riiimparm wants to merge 13 commits into
developfrom
feature/heading-breadcrumb-bar

Conversation

@riiimparm

@riiimparm riiimparm commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

変更内容

記事の見出し階層をヘッダー直下のパンくずバーで表示。

スクリーンショット 2026-08-14 11 14 22
テスト用md
---
title: 【検証】見出しパンくずバーの動作確認用デモ記事
pubDate: '2026-08-13'
description: 目次を通過した後にヘッダー直下へ現在地パス(h2 > h3 > h4)を表示するパンくずバー機能を確認するためのダミー記事
author: RiiiM
tags: [Tech]
---

この記事はパンくずバー検証用のダミー記事です。実装内容の確認をしやすくするため、
h2 → h3 → h4 のネスト構造をいくつか用意し、それぞれの配下にスクロールで
バーの表示切り替えを確認できる程度の分量の本文を入れています。

目次(このすぐ下の一覧)を通過してスクロールすると、ヘッダーのすぐ下に薄い帯が
現れ、現在読んでいる場所を「h2の見出し > h3の見出し > h4の見出し」という
パス形式で表示します。現在地の見出し(一番深い階層)は白文字、その親階層は
薄い白文字で区別されます。見出しをまたぐたびにパスの中身が即座に切り替わる
だけで、フォントサイズの拡大縮小やスライドなどのアニメーションは行いません。

## 第一部: 基本のバー表示確認

このセクションではh2見出しを通過した時点でパンくずバーに表示される様子を
確認します。以下のダミー本文は特に意味のある内容ではなく、スクロール量を
稼ぐためのものです。

あいうえおの練習帳というものが昔から存在しており、文字の練習をするために
同じ行を何度も書き取るという学習方法が広く使われてきました。これは筆記の
反復によって手が形を覚えることを狙ったものであり、単純な繰り返しであっても
一定の効果があるとされています。

同様に、ダミーテキストというものはレイアウト確認のために古くから使われており、
「あかさたなはまやらわ」のような五十音の並びを利用して文章量を調整することが
よくあります。内容そのものに意味は無くとも、行間や余白、フォントサイズの
挙動を確認する上では十分に役立ちます。

### 第一部 - その一: h3見出しのバー表示確認A

ここはh3見出しです。スクロールするとバーのパスが「第一部 > このh3」に
更新されるはずです。以下、確認用のダミー本文を続けます。

かきくけこの段落その一。文章の長さを稼ぐための繰り返しですが、実際の記事
のように段落を複数に分けることで、スクロール中にバーの表示がどのタイミングで
切り替わるかを確認しやすくしています。

かきくけこの段落その二。引き続きダミーの文章です。特に技術的な内容は
含まれていません。

#### 第一部 - その一 - 詳細: h4見出しのバー表示確認

ここはh4見出しです。h2, h3, h4の三段のパスがすべてバーに表示される状態を
確認するための最終段です。

さしすせその段落。この段落まで読み進めた時点で、バーには
「第一部 > 第一部 - その一 > 第一部 - その一 - 詳細」の三階層が
表示されているはずです。

### 第一部 - その二: このセクションだけ意図的にとても長いタイトルを付けて折り返しではなく省略のされ方を確認するためのh3見出しです

こちらは同じh2配下の二つ目のh3で、パンくずバーの省略(ellipsis)動作を
確認するために見出しをあえて長くしています。バー幅が足りない場合は、
先に親階層(このh3自身が親になるh4のバー表示時など)の文字列側が
省略され、現在地として表示される一番深い階層の文字列は最後まで
読める状態が優先されます。

たちつてとの段落。入れ替わりのタイミングを確認するための本文です。
ある程度の分量がないとスクロール距離が足りず確認しづらいため、
数段落分のダミーテキストを用意しています。

たちつてとの段落その二。引き続きダミー文章です。

## 第二部: 別のh2セクションでの確認

ここからは二つ目のh2セクションです。前のh2セクションを通り過ぎることで、
バーの一番浅い階層がこのh2に入れ替わる様子を確認できます。

なにぬねのの段落。二つ目のh2セクション配下の本文です。引き続きダミー
テキストを用いてスクロール量を確保しています。

### 第二部 - その一: h3見出しのバー表示確認C

このh3もバー表示動作の確認用です。

はひふへほの段落。ダミー本文その一。

はひふへほの段落その二。ダミー本文その二。内容に意味はありません。

### 第二部 - その二: h3見出しのバー表示確認D

もう一つのh3です。

まみむめもの段落。ここでもスクロール量を確保するためのダミー文章を
並べています。

まみむめもの段落その二。これで第二部は終わりです。

## 第三部: 三つ目のh2セクション

最後の確認用セクションです。ここまでスクロールすると、バーの表示が
すべて入れ替わっているはずです。

やゆよらりるれろの段落。最終セクションのダミー本文です。

わをんの段落。これで検証用記事の本文は終了です。お疲れ様でした。

rehype-tocが生成する.tocを2カラムグリッドで本文脇に固定し、
IntersectionObserverで現在読んでいるセクションのリンクをハイライトする。
新規ライブラリは追加せずネイティブAPIのみで実装。
前回のtoc sidebar化(gridレイアウト+toc sticky+scrollspyハイライト)は
方針転換のため差し戻し、.tocは無変更に戻した。

代わりにVSCodeのSticky Scrollのような挙動を実装:
記事中のh2/h3/h4をクライアントサイドJSでネストしたラッパー
(.stack-section > .stack-heading + .stack-content)に組み替え、
各見出しをposition:stickyで階層順にヘッダー下へ積み重ねる。
ネストしたsticky要素は所属セクションを抜けると自然に外れる
(CSSのposition:stickyの挙動のみで実現、追加のJS制御は不要)。

見出しがスタック位置に固定される直前の約4rem分のスクロール量に
連動して、CSSカスタムプロパティ(--stack-progress)経由でfont-sizeを
本来のサイズからスタック時サイズへ連続的に縮小させる。
VSCode風の見出しネストスティッキースタック(DOM再構成+stack-progressに
よるフォントシュリンク)は撤回し、目次通過後にヘッダー直下へ現在の
h2 > h3 > h4パスを表示する薄いパンくずバーに置き換えた。DOMは元の
フラットな見出し構造のまま、スクロール位置から現在アクティブな見出しを
算出して表示するだけのシンプルな実装。
- 長い見出しで現在地(白文字)側が消えないよう、親階層側を別要素に分離しflex-shrink:0の現在地を優先して残す形に変更
- バー内側をヘッダーと同じcontainerクラスでラップし左端をロゴと揃える
- document.fonts.readyとResizeObserverでフォント読み込み後・レイアウト変動後も見出し位置キャッシュを更新
- デモ記事の説明文を旧ネストスタック方式からパンくずバー方式の説明に更新し、省略確認用の長い見出しを追加
@riiimparm riiimparm linked an issue Aug 13, 2026 that may be closed by this pull request
BlogLayout.astroにインライン実装されていたdiv/script/styleを
src/components/HeadingBreadcrumbBar.astroへ移動。機能・見た目の変更なし。
@riiimparm riiimparm self-assigned this Aug 14, 2026
@riiimparm
riiimparm requested a review from naoki-00-ito August 14, 2026 16:28
Comment thread src/components/HeadingBreadcrumbBar.astro Outdated
---

<div id="heading-crumb" class="heading-crumb" hidden>
<div class="heading-crumb__inner container">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@riiimparm
.container って使ってる?

@riiimparm riiimparm Aug 22, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ヘッダのロゴと左パディング合わせるためにつかっているよ
https://github.com/rowicy/web/pull/187/changes/BASE..07b3d18ed2193f3eb29b0001c42a4b7e27c36243#diff-f0c73cf94d48f7809de7c98c6359afa6db7728eddfcb8e98abee71c0a3bbb53aR155-R164

hiddenは最初のh2要素のスクロールが通過するまでパンくずバーを隠しておくため

Comment thread src/components/HeadingBreadcrumbBar.astro Outdated

---

<div id="heading-crumb" class="heading-crumb" hidden>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@riiimparm
スマホサイズなど、画面幅狭いと見切れるので、横スクロールできるようにしても良いかも!
Image

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

29e5d27
で実装

ファイル名(HeadingBreadcrumbBar.astro)とDOM上のid/classが
heading-crumbのままずれていたため、子要素のクラス名
(__inner, __ancestors, __item, __item--current, __sep)も含めて
heading-crumb-barに揃えた。機能・見た目の変更なし。
sepのテキストを' > 'としていたため、currentItemフレックスアイテムの
先頭子要素になるケース(祖先→現在地の境目)で、CSSの空白つぶしにより
先頭のスペースだけ描画上消え「実装> Claude Codeをインストール」の
ように左側の余白が無くなっていた。祖先同士をつなぐsep(同一span内の
途中に位置する)ではこの問題は起きないため、階層や文言によって
余白の有無が不揃いに見えていた。

space文字をやめて'>'のみとし、margin: 0 0.3emで余白を作ることで、
flexアイテム境界の位置によらず常に安定した余白になるようにした。
見出しが長い場合に横スクロールを可能にした前回の実装は、
ヘッダーと同じcontainerクラスのpaddingをスクロール対象の要素に
直接持たせていたため、スクロール終端でそのpaddingが失われ、
長い見出しが左右マージンを無視して画面端まではみ出してしまう
問題があった。

.heading-crumb-bar__inner(containerのpadding、常に固定・非スクロール)
の内側に新設した.heading-crumb-bar__track(overflow-x:auto)を置き、
実際にスクロールする要素をtrackだけに限定。マージン領域は常に
バー背景色のみで、どれだけ長い見出しが来てもテキストがマージンに
はみ出さないようにした。

あわせて、自動スクロールの挙動を「現在地見出しの末尾」ではなく
「先頭」が見える位置に変更(currentItemの左端をtrackの左端に揃える)。
.heading-crumb-bar__innerのpadding-top(0.4rem)を削除し、
ヘッダー直下に隙間なく積み重なるようにした。padding-bottomは
テキストとしての読みやすさのため維持。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

セクションのパンくずを表示

2 participants