AstroとShikiのコードブロックで樹形図の縦線をつなぐCSS調整

コードブロックに置いた樹形図の│が、行ごとに細かく切れていました。line-height: 1.45まで詰めても、縦線はつながりません。2026 年 8 月 22 日の hibanas-net では、行ボックスをもう一段見直して1.15へ下げました。
変更したのはsrc/styles/main.cssだけです。Markdown の図は触っていません。私は運用手順をテキスト図で残すことが多いため、ここが崩れると装飾ではなく情報の経路が読みにくくなります。
前回の調整で残った問題
PR #32 では、本文から継承していたline-height: 1.75をコードブロック内だけ1.45へ変えました。Shiki の各行にはdisplay: blockとmin-height: 1.45emも指定しました。コードの行間は縮まりましたが、樹形図の縦棒にはまだ空白が残りました。
PR #34 で、残った隙間を次のように詰めています。
| 前回完了時 | 今回完了後 |
|---|---|
preの行間は1.45です | pre、code、.lineを1.15にそろえました |
Shikiの.lineはdisplay: blockです | .lineをinline-blockにしました |
| 文字間隔はデフォルト値です | 樹形図の区画だけletter-spacing: 0にしました |
.lineの最小高さは1.45emです | 最小高さを1.15emに合わせました |
すでに原因を切り分け済みなら、「本番 CSS を 3 階層でそろえる」まで飛ばせます。
なぜMarkdownを直さないのか
次のような図は、文字そのものが線を作ります。
記事のMarkdown
└─ Astro 7.2.0
└─ ShikiがコードフェンスをHTMLへ変換します
└─ pre
└─ code
├─ span.line
├─ span.line
└─ span.line
│の前後へ文字を足しても、行と行の間にできた空白は埋まりません。問題は文字列ではなく、ブラウザーが作る行ボックスの高さです。MDN によると、line-heightは横書きで行ボックスの高さを決めます。また、このプロパティは子要素へ継承されます。
Astro は Markdown のコードフェンスを Shiki で装飾します。hibanas-net ではpreの中にcodeがあり、その中の.lineが各行を持ちます。親だけを変えて終わりにせず、この 3 階層の計算値をそろえる必要がありました。
本文の行間まで1.15にはしません。MDN は本文に1.5以上を勧めています。今回は罫線文字を含むコードブロックだけを狭くします。私は、本文の読みやすさとテキスト図の連続性を別の設定として扱う方が安全だと考えています。
用語表
| 用語 | ここでの意味 |
|---|---|
| コードフェンス | Markdownを3個のバッククォートで囲むコードブロックです |
| Shiki | TextMateの文法とテーマを使うシンタックスハイライターです |
| 行ボックス | 横書きで1行分の高さを持つCSS上の箱です |
| 単位なしの行高 | フォントサイズへ掛ける1.15のような数値です |
| box-drawing文字 | │、├、└など、線や枝を表すUnicode文字です |
.line | Shikiがコードの1行を包むspan要素です |
本番CSSを3階層でそろえる
2026 年 8 月 23 日時点のorigin/mainにある指定です。テーマや Markdown 設定は変えず、コードブロックの箱だけを調整しています。
.content pre {
background-color: #1a1b26 !important;
color: #e1e4e8 !important;
white-space: pre !important;
overflow-x: auto;
overflow-wrap: normal !important;
word-break: normal !important;
line-height: 1.15 !important;
letter-spacing: 0;
}
.content pre code {
display: block;
width: 100%;
background-color: transparent !important;
color: inherit;
padding: 0 !important;
border-radius: 0 !important;
font-size: inherit;
font-weight: inherit;
line-height: 1.15;
letter-spacing: 0;
}
.content pre .line {
display: inline-block;
width: 100%;
line-height: 1.15;
padding: 0;
margin: 0;
min-height: 1.15em;
}
.lineをinline-blockにしても、width: 100%で 1 行分の幅を保ちます。paddingとmarginは 0 です。min-heightも行高と同じ1.15emにして、別の値から余白が戻らないようにしています。
!importantはむやみに増やしていません。既存の Tailwind Typography と Shiki のインラインスタイルに対し、preの背景、文字色、空白処理、行高を本番側で固定する箇所だけに残しています。
実際のマージ差分を確認する
まず、PR #34 のマージコミットが触った範囲を見ます。
git show --stat --oneline 2e42fbc8902af204ab0c33e18c1eb1a1189a4c60
実行結果です。
2e42fbc design: コードブロックの樹形図の縦線がつながるように行間を詰める (#34)
src/styles/main.css | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
記事や Markdown を変更していないことも、この出力から確認できます。次に、現在の 3 セレクターを Node.js で取り出します。
node -e "const fs=require('fs');const css=fs.readFileSync('src/styles/main.css','utf8');for(const selector of ['.content pre {','.content pre code {','.content pre .line {']){const i=css.indexOf(selector),j=css.indexOf('}',i);console.log(css.slice(i,j+1).replace(/^ /gm,''));}"
出力には、次の組み合わせが含まれます。
.content pre {
line-height: 1.15 !important;
letter-spacing: 0;
}
.content pre code {
line-height: 1.15;
letter-spacing: 0;
}
.content pre .line {
display: inline-block;
width: 100%;
line-height: 1.15;
min-height: 1.15em;
}
実際の出力には背景色や余白の指定も表示されます。確認点は、3 階層の1.15と.lineのinline-blockです。
buildでMarkdown全体への影響を止める
CSS 変更後は、対象ページだけを眺めて終わらせません。Astro の型検査と静的 build を通します。
node_modules/.bin/astro check
node_modules/.bin/astro build
成功時は両方が終了コード 0 になります。hibanas-net では記事を静的 HTML へ変換するため、Shiki がコードフェンスを処理できない場合や、frontmatter が壊れた場合もここで止まります。
見た目の確認では、普通のコードと樹形図を同じページへ置きます。樹形図だけを直して、長いシェルコマンドが重ならないことも見ます。横幅を超えた行はoverflow-x: autoでスクロールできる状態を保ちます。
よくあるエラー
| 症状 | 原因 | 対応 |
|---|---|---|
1.45へ下げても│が切れます | .lineの箱に高さが残っています | pre、code、.lineの計算値を順に確認します |
| 縦線はつながったのにコードが重なります | 行高をフォントに対して下げすぎています | 1.15を下限の目安にして、使用中のフォントで再確認します |
| 1行が横へ伸びず折り返されます | .lineの幅かwhite-spaceが変わっています | width: 100%とwhite-space: preを確認します |
| 本文まで窮屈になります | .content全体へ行高を指定しています | セレクターを.content pre以下に限定します |
| Shikiの色が消えます | spanの色まで一括上書きしています | 行間の指定とトークン色の指定を分けます |
| buildは通るのに図が切れます | buildは画面上の連続性を判定しません | 実ブラウザーで樹形図と通常コードを確認します |
テキスト図を運用資料として扱う
AI エージェントの処理経路や公開ゲートは、スクリーンショットよりテキスト図の方が差分を追いやすい場面があります。Git で 1 文字単位の変更が見え、検索もできます。だから、縦線の切れは小さな見た目の問題として放置しませんでした。
今回の修正は CSS の 15 行だけです。しかし、対象をコードブロック内に閉じ、前回の1.45から何が足りなかったかを履歴に残しました。私はこのような調整でも、Markdown を書き換えて症状を隠すより、描画の責任を持つ層で直す方を選びます。
一次情報
| 出典 | 確認した内容 |
|---|---|
| Astro: Syntax Highlighting | MarkdownのコードフェンスはデフォルトでShikiが処理します |
| Shiki: Introduction | ShikiはTextMateの文法とテーマを使うシンタックスハイライターです |
| MDN: line-height | 行ボックスの高さ、継承、単位なし数値、本文の可読性を確認しました |
| MDN: display | blockとinline系の外側表示型を確認しました |
