基本的に文字というものは、大文字・小文字など文字の種類によって目に見える大きさ(高さ)が異なります。
例えばCSSで font-size
を100pxに指定した場合でも、文字がピッタリ100pxで表示されるわけではありません。
これをCSSで思い通りに指定する方法を調べてみました。
(欧文フォントの場合)
欧文フォントの基礎知識
アルファベットでは、文字の下端( y
などの下に飛び出る小文字を除く)となるベースラインを基準に、デザイン上の指標となる高さがいくつか存在します。
- アセンダ:ベースラインから
b
や d
など小文字で上に飛び出る部分の上端までの距離
- ディセンダ:ベースラインから
j
や y
など下に飛び出る文字の下端までの距離
- エックスハイト:ベースラインから
x
など、小文字の上端までの距離
- キャップハイト:ベースラインから大文字の上端までの距離。アセンダより少し下に位置することが多い
※こちらの図がわかりやすいです http://w3.kcua.ac.jp/~fujiwara/infosci/font.html
例えば Arial
のメタデータを解析してみると、下記の値を発見できます
- ascender: 1854
- descender: 434
- sxHeight: 1062
- sCapHeight: 1467
数字の大小はさておき、これらの値でまず意識しなければならないのは単位です。
実はこの数字、単位はピクセルでもミリメートルでもありません。
各フォントが em-square
という基準値を決め、それに対する相対値として定義されています。
これもメタデータを見てみると発見できます
要するに Arial
の場合は、2048を基準に、それよりどのくらい大きいのか、小さいのか、という相対的な数字なのです
文字サイズ16pxのxの大きさ
そしてこの em-square
こそがCSSの font-size
と直接関わってくる部分。
例えば font-size: 16px;
とする場合、xの高さは
var xHeight = (1062 / 2048) * 16px
約8.3pxとなります。
また、逆算的にキャップハイトが100pxになるためのfont-sizeは
var fontSize = 100px / (1467 / 2048)
約139.6pxになります。
font-size
は、実は スケール感をふんわり指定しているだけ で、必ずしもその大きさで文字が表示されるわけではない、ということが分かって頂けたかと思います。
文字の表示位置とline-height
ここまでで表示したい大きさのfont-sizeは見いだせるようになったと思いますが、実際にこれをウェブのレイアウトで使うためには、表示位置も制御できねば意味がありません。
em-square
や ascender
などの値はあくまで距離の数値なので、そのまま位置算出に使うことはできなさそうです。
CSSでインライン要素の表示位置といえば vertical-align
ですが、これはベースラインを揃えたりなど、わりとアバウトな配置の指示しかできませんし、 line-height
の設定値次第で文字の表示位置は大きく変わります。
line-height
に関して言えば、実はデフォルト値である normal
は、下記の計算式で算出されているみたいです
var lineHeight = (ascender + descender + lineGap) / unitsPerEm
lineGap
は、他の値と同じようにフォントのメタデータとして記録されていて、例えばArialは 67
です。フォントによっては0なこともあります。
ascender + descender
が文字の表示しうる範囲ですが、lineGapはその半分の数値がascenderの上とdescenderの下に割り振られるような表示になります。
上記の式をArialのメタデータで計算してみると、結果は 1.1499
になります。約1.15です。
実際に下記のようなCSSを使ってp要素の高さをDevToolsで見てみると、115pxになってるのが確認できるはずです。
p {
font-family: 'Arial';
font-size: 100px;
line-height: normal;
}
ということは、 line-height: normal
を指定してJSで高さを取得し、他のメタデータからBaselineの位置を算出することで最終的にはCapHeightやxHeightなどの表示位置も計算できるはずです。
var baselineY = lineHeight - (lineGap / 2 + descender) / unitsPerEm
var xHeightY = baselineY - sxHeight / unitsPerEm
var capHeightY = baselineY - sCapHeight / unitsPerEm
結論は、CSSでフォントを深く掘るのはつらいということです