CSSで、日本語のかっこや句読点の詰め方を整える方法
日本語のかっこや句読点の詰め方は、CSS の text-spacing-trim プロパティで変えられます。Chrome と Edge では、」「 のように隣り合ったかっこの間の空きは、何も書かなくても半分に詰まります。行頭のかっこも詰めたいときは trim-start、詰めずに昔の見た目に戻したいときは space-all を指定します。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Noto Sans CJK JP と IPAゴシックを入れ、横書きのページを Playwright で開いて、1文字ずつの幅を測りました。縦書き、Chrome 以外のブラウザー、Windows や macOS に入っているフォントでの表示は試していません。各ブラウザーの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。
何もしなくても、隣り合うかっこは詰まる
かっこや句読点の多くは、漢字と同じ全角の幅を持ちながら、字形の片側に空きがあります。そのため、」「 や )、 のように並ぶと、空きが重なって間が広く見えます。
text-spacing-trim の初期値 normal は、この重なった空きを半分に詰めます。CSS の仕様では、初期値は normal で、子要素に継承されると定められています。
検証環境で、何も指定しない段落と space-all を指定した段落の、1文字ずつの幅を測りました。1.00 が全角、0.50 が半角です。
段落に入れた文字列は 「東」「東」(東)、東。 です。
| 並び | 測った文字 | 指定なし(normal) | space-all |
|---|---|---|---|
」「 |
「 |
0.50 | 1.00 |
」( |
( |
0.50 | 1.00 |
)、 |
) |
0.50 | 1.00 |
)、 |
、 |
1.00 | 1.00 |
| 行全体 | 12文字の幅の合計 | 10.51em | 12.01em |
閉じかっこのあとに始めかっこが来ると始めかっこが半角になり、閉じかっこのあとに読点が来ると閉じかっこが半角になりました。12文字の行が、1.5文字分短くなっています。

句点と閉じかっこが続く「はい。」の 。」 でも、句点が半角になりました。どの組み合わせで詰めるかの規則は、MDN の「全角幅の約物の折り畳み」の節にまとめられています。
詰めずに、すべてのかっこと句読点を全角のまま並べたいときは、space-all を指定します。
body {
text-spacing-trim: space-all;
}
行頭のかっこも詰めるには trim-start
初期値の normal では、行の頭に来た始めかっこは全角のままです。かっこの左に半角の空きが残るので、ほかの行より半文字分、右にずれて見えます。行頭の始めかっこも半角にして、行の左端をそろえたいときは trim-start を指定します。
body {
text-spacing-trim: trim-start;
}
段落の最初の行の始めかっこだけは全角で残し、折り返して行頭に来たかっこだけを詰めたいときは、space-first を使います。MDN では、段落の最初の行と、強制改行(<br> など)の直後の行で、行頭の始めかっこを全角にする値と説明されています。検証環境では、それ以外の行(自動で折り返した行)の行頭の始めかっこは半角になりました。
検証環境で、幅を5文字分にした段落に次の内容を入れ、3つの行の頭にある 「 の幅を測りました。
<p>「東京」<br>「大阪」と「名古屋」</p>
1行目は段落の最初、2行目は <br> の直後、3行目は自動で折り返した行です。
| 値 | 段落の最初 | <br> の直後 |
自動の折り返し |
|---|---|---|---|
| normal(初期値) | 1.00 | 1.00 | 1.00 |
| space-all | 1.00 | 1.00 | 1.00 |
| space-first | 1.00 | 1.00 | 0.50 |
| trim-start | 0.50 | 0.50 | 0.50 |

text-spacing-trim は子要素に継承されます。検証環境でも、body に trim-start を指定すると、中の段落の行頭のかっこが半角になりました。サイト全体にまとめて効かせるなら、body に1回書けば足ります。
フォントに halt か chws の機能がないと効かない
かっこを半角にするには、フォントの中に半角の字形の情報が必要です。MDN には、フォントが OpenType の halt か chws の機能を持っていないと text-spacing-trim は無効になる、と書かれています。
検証環境の2つのフォントを、Python のライブラリ fontTools で調べると、Noto Sans CJK JP は halt を持ち、IPAゴシックはどちらも持っていませんでした。次のコードで、IPAゴシックのファイル(ipag.ttf)を調べると False False と出ます。
from fontTools.ttLib import TTFont
font = TTFont("ipag.ttf")
tags = set()
if "GPOS" in font:
tags = {r.FeatureTag for r in font["GPOS"].table.FeatureList.FeatureRecord}
print("halt" in tags, "chws" in tags)
IPAゴシックで同じ文章を表示すると、初期値でも trim-start を指定しても、かっこと句読点はすべて全角の 1.00 のままでした。text-spacing-trim を書いても見た目が変わらないときは、表示に使われているフォントがこの機能を持っているかを確かめてください。
行末の句点は、詰めて行に収めてはくれなかった
仕様の normal は、行末の閉じかっこや句読点が行に入りきらないとき、半角にして収めることを許しています。
検証環境で、幅を9.5文字分にした段落に「東」を9つ、「。」、そのあとに「東」を4つ続けて入れました。「。」を半角にすれば9.5文字分で1行目に収まります。ところが、初期値、space-all、trim-start のどれでも、1行目は「東」8文字で終わりました。「。」は半角にならず、直前の「東」といっしょに2行目へ送られています。行末の句読点を行の外にぶら下げる hanging-punctuation という別のプロパティもありますが、互換性データでは Chrome と Edge は対応していません。
Chromium では、同じ文章を並べて比べると行頭の詰め方が揃ってしまう
値の違いを見比べるために、同じ文章の段落を1ページに並べて値だけを変えると、検証環境の Chromium 153 では正しく比べられませんでした。
1つ目の段落を normal、2つ目を trim-start にして、どちらにも「「東」「東」」を入れると、2つ目の行頭の「も全角の 1.00 になりました。順番を入れ替えると、今度は normal の段落の行頭の「が半角になりました。どちらも、ページの中で先に置いた段落の、行頭の詰め方が使われています。2つ目の段落の最後の字だけを「西」に変えると、どちらの段落も値どおりの幅になりました。
隣り合うかっこの詰め方は、同じ文章でも normal と space-all で正しく違いが出ました。この記事の画像は、値ごとに別のページを開いて撮り、あとから縦に並べています。
Chrome と Edge だけが対応している
互換性データでは、text-spacing-trim と4つの値(normal、space-all、space-first、trim-start)は、Chrome と Edge が 123、Android の Chrome が 123 から使えます。Firefox と Safari(iOS の Safari を含む)は対応していません。互換性データと MDN では、実験的な機能として扱われています。
仕様には trim-both、trim-all、auto などの値もありますが、MDN によると、どのブラウザーもまだ実装していません。





