CSSのpaltで、日本語の文字のあいだを詰めて組む方法
日本語の文字のあいだを詰めて組むには、CSS で font-feature-settings: "palt" を指定します。フォントの中にある詰め方の情報(OpenType の palt という機能)が使われ、かなやかっこ、句読点が、字形に合った幅で並びます。フォントがこの機能を持っていないと、指定しても何も変わりません。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。フォントは Noto Sans CJK JP、IPAゴシック、IPA Pゴシックを使い、検証用のページを Playwright で開いて、1文字ずつの幅を測りました。Firefox と Safari、Windows や macOS に入っているフォント、Web フォントとして読み込んだフォントでの表示は試していません。各ブラウザーの対応バージョンは、互換性データ(@mdn/browser-compat-data 8.1.8)の値です。

詰めたい要素に palt を指定する
詰めたい要素に font-feature-settings: "palt" を指定します。
h1,
h2 {
font-feature-settings: "palt";
}
"palt" のように機能の名前(4文字のタグ)だけを書くと、その機能がオンになります。MDN の説明では、名前のあとに on や 1 を付けても同じ意味で、off か 0 を付けるとオフになります。font-feature-settings は子要素に継承されます(CSS Fonts Level 4 の仕様)。
どの文字が、どれだけ詰まるか
検証環境で、Noto Sans CJK JP の 20px の文字を1つずつ測りました。単位は em(文字の大きさに対する割合)で、1.00 が全角です。
| 文字 | 指定なし | palt |
|---|---|---|
「
」
、
。 |
1.00 | 0.50 |
こ |
1.00 | 0.87 |
り |
1.00 | 0.83 |
ね |
1.00 | 1.01 |
タ |
1.00 | 0.88 |
手
借 |
1.00 | 1.00 |
A |
0.61 | 0.61 |
かっこと句読点は半分の幅になりました。ひらがなとカタカナは、字の形に合わせて 0.83〜0.96 ほどに狭まります。ね のように、わずかに広くなる字もありました。漢字は全角のままで、英字の幅も変わりません。
「ねこの手」を、借りたい。カタカナとABC という行全体では、指定なしが 19.90em、palt が 16.95em で、3文字分ほど短くなりました。
かっこと句読点だけを詰めたいときは halt
Noto Sans CJK JP は、halt という機能も持っています。同じ行に font-feature-settings: "halt" を指定すると、かっこと句読点だけが 0.50 になり、かなは 1.00 のままでした。行全体は 17.90em です。
かっこが続くところも、半分より狭くはならなかった
」「 のように続くかっこの空きは、text-spacing-trim というプロパティでも詰められます。検証環境の Chromium と Noto Sans CJK JP では、何も書かなくても 」「 の 「 が 0.50 になりました(MDN では実験的な機能とされ、フォントが halt か chws を持っていないと効きません)。palt と重なって詰めすぎにならないかを、「東」「東」(東)、東。 という行で確かめました。
palt を指定すると、かっこと句読点はすべて 0.50 になり、行全体は 8.00em でした。続くかっこが 0.50 よりさらに狭くなることはありませんでした。palt に text-spacing-trim: space-all(詰めない指定)を足しても、8.00em のままでした。
フォントが palt を持っていないと変わらない
palt は、フォントの中にある情報を使います。Python のライブラリ fontTools で調べると、Noto Sans CJK JP は palt を持ち、IPAゴシックは持っていませんでした。次のコードで、IPAゴシックのファイル(ipag.ttf)を調べると 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("palt" in tags)
IPAゴシックで同じ行に palt を指定すると、すべての文字が指定なしと同じ幅で、行全体も 19.50em のまま変わりませんでした。指定しても見た目が変わらないときは、表示に使われているフォントがこの機能を持っているかを確かめてください。
IPA Pゴシックのように、字の幅が最初からそれぞれ違う(プロポーショナルな)フォントもあります。IPA Pゴシックは palt を持っていませんが、指定なしでも行全体は 16.67em で、Noto Sans CJK JP に palt を指定したときと近い幅でした。
font-variant-east-asian の proportional-width では詰まらない
MDN の font-feature-settings のページでは、できる限り font-variant-east-asian などの個別のプロパティを使うべきだとされています。ただ、font-variant-east-asian の proportional-width は、palt ではなく pwid という別の機能に対応しています。
検証環境で font-variant-east-asian: proportional-width を指定すると、かなとかっこ、句読点の幅は 1.00 のまま変わりませんでした。変わったのは、全角の英数字です。
| 文字 | 指定なし | proportional-width | palt |
|---|---|---|---|
A |
1.00 | 0.61 | 0.78 |
1 |
1.00 | 0.56 | 0.76 |
ね |
1.00 | 1.00 | 1.01 |
、 |
1.00 | 1.00 | 0.50 |
全角の A は、半角の A と同じ 0.61 になりました。文字のあいだを詰める目的なら、font-feature-settings で palt を指定します。
CSS Fonts Level 4 の仕様にある横書きのカーニングの手順では、font-kerning でカーニングを有効にしたとき、フォントが palt を持っていれば palt を適用します。検証環境の Chromium 153 では、font-kerning: normal を指定しても、行全体は 19.90em のままで詰まりませんでした。
子要素で font-feature-settings を書くと、palt が外れる
font-feature-settings は、親と子の指定が足し合わされません。仕様の font-feature-settings の節にも、値はまとめて1回で設定され、継承した値に機能を1つずつ足したり外したりする方法はない、と書かれています。子要素で別の機能を書くと、親から継承した palt は外れます。
検証環境で、body に palt を指定し、中の span に次の3通りの指定をして、「ねこの手」 の6文字の幅を測りました。
body {
font-feature-settings: "palt";
}
/* 1. palt が外れる */
span {
font-feature-settings: "tnum";
}
/* 2. palt も並べて書く */
span {
font-feature-settings: "palt", "tnum";
}
/* 3. 数字の幅は個別のプロパティで指定する */
span {
font-variant-numeric: tabular-nums;
}
| span の指定 | 計算された font-feature-settings | 「ねこの手」 の幅 |
|---|---|---|
| なし | "palt" |
4.84em |
1. "tnum" だけ |
"tnum" |
6.00em |
2. "palt", "tnum" |
"palt", "tnum" |
4.84em |
3. font-variant-numeric |
"palt" |
4.84em |
"tnum" だけを書いた span では、palt を指定しない場合と同じ 6.00em に戻りました。子要素でほかの機能を足すときは、palt も並べて書くか、font-variant-numeric のような個別のプロパティを使います。
本文に使うと、行ごとの文字数と右端の位置が変わる
palt を指定すると、字によって幅が変わるので、1行に入る文字数も行ごとに変わります。
検証環境で、幅を15文字分にした段落に同じ文章を入れ、各行の文字数と右端の位置を測りました。
| 行 | 指定なし | palt | palt と justify |
|---|---|---|---|
| 1行目 | 15文字、15.00em | 15文字、14.11em | 15文字、15.00em |
| 2行目 | 15文字、15.00em | 16文字、14.74em | 16文字、15.00em |
| 3行目 | 15文字、14.95em | 16文字、14.97em | 16文字、15.00em |
| 4行目 | 14文字、13.90em | 17文字、14.93em | 17文字、15.00em |
| 5行目 | 12文字、11.77em | 7文字、5.80em | 7文字、5.80em |
指定なしでは、1〜3行目がどれも15文字で、右端は 15.00em と 14.95em でした。4行目は14文字で、右端は 13.90em でした。palt を指定すると、文字数が行ごとに15〜17文字と変わり、最後の行を除く右端は 14.11em から 14.97em まで、行によってずれました。段落に text-align: justify を足すと、最後の行以外の右端は 15.00em にそろいました。
縦書きでは vpal を使う
仕様のカーニングの手順では、横書きで palt、縦書きで vpal を使います。縦書き(writing-mode: vertical-rl)の段落に palt を指定しても、検証環境では文字の高さは変わりませんでした。縦書きで詰めるときは、vpal を指定します。

.vertical {
writing-mode: vertical-rl;
font-feature-settings: "vpal";
}
Noto Sans CJK JP は vpal も持っています。vpal では、かっこと句読点が 0.50、かなが 0.87〜0.96 になり、「ねこの手」を、借りたい。 の列の高さは 13.00em から 10.55em になりました。
主要なブラウザーで使える
互換性データでは、font-feature-settings は Chrome 48、Edge 12、Firefox 34、Safari 9.1、iOS の Safari 9.3、Android の Chrome 48 から使えます。ただし、詰まり方はフォントしだいです。閲覧する端末に入っているフォントが palt を持っていなければ、その端末では詰まりません。





