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

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: blockmin-height: 1.45emも指定しました。コードの行間は縮まりましたが、樹形図の縦棒にはまだ空白が残りました。

PR #34 で、残った隙間を次のように詰めています。

前回完了時今回完了後
preの行間は1.45ですprecode.line1.15にそろえました
Shikiの.linedisplay: blockです.lineinline-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個のバッククォートで囲むコードブロックです
ShikiTextMateの文法とテーマを使うシンタックスハイライターです
行ボックス横書きで1行分の高さを持つCSS上の箱です
単位なしの行高フォントサイズへ掛ける1.15のような数値です
box-drawing文字など、線や枝を表すUnicode文字です
.lineShikiがコードの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;
}

.lineinline-blockにしても、width: 100%で 1 行分の幅を保ちます。paddingmarginは 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.lineinline-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の箱に高さが残っていますprecode.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 HighlightingMarkdownのコードフェンスはデフォルトでShikiが処理します
Shiki: IntroductionShikiはTextMateの文法とテーマを使うシンタックスハイライターです
MDN: line-height行ボックスの高さ、継承、単位なし数値、本文の可読性を確認しました
MDN: displayblockinline系の外側表示型を確認しました
この記事をシェア