[CSS]合成フォントの話とやりがちミス
CSS組版アドベントカレンダー2024の9日目の記事です。
それは合成フォントじゃないよ
日本語文中で日本語と英単語のフォントを変えたいときどうしてますか?
:root {
--main-font: 'Times New Roman', 'Noto Serif JP', serif;
}
body {
font-family: var(--main-font);
}
英単語部分がTimes New Romanに、日本語部分がNoto Serif JPになってめでたしめでたし。それはそれでよいのですが、組版で望まれる合成フォントとはちょっと違います。
これは「日本語を表示しようとしたら最初に指定されたTimes New Romanの中に日本語の字形が無いので、2番目に指定されたNoto Serif JPが適用される」という、フォント選択の機構による挙動です。
「何が違うんだ」というと、分かり易いものとして次のトピックがあります:
- (このケースでは)1番目のフォントが2番目のフォントが適用されてほしい字形を持っていてはいけない
- フォント同士の大きさの調整をどうする
font-size-adjust
まあ、フォント同士のサイズについては実はこの段階からでも使えるプロパティがあります。font-size-adjust
プロパティです。
使い方についてはMDNに分かり易く載っているので割愛。単純に縮尺を指定することもできますし、典型的な単位に使われるex-height
やic-height
なんかを基準に伸縮もできます。説明にあるように、基本的には最初のフォント指定に合わせて2番目以降のフォントサイズを調整します。
つまり、3種以上のフォントを一度に組み合わせるのは多分厳しい。
CSSにはもっとちゃんと(?)合成フォントをやる機構があります。@font-face
です。
@font-face
新しめのドラフトだと複雑だしバリアブルフォントまわりは馴染んでいないので、hidarumaが使っている範囲で。
基本
@font-face {
font-family: 'myfont';
src: local('Noto Sans JP');
}
body {
font-family: 'myfont';
}
はい。@font-face
で定義したmyfontを、bodyのfont-family
に指定しています。これは、ただフォントに別名を付けただけですね。
src
に指定したフォントが実際のフォントですが、local()
としていることから分かるようにurl()
で、Web上に配置されたフォントを指定することもできます。
仕様にはformat()
などの指定値もありますが、基本的には処理系が良い感じに自動設定してくれるので、上手くいかなかったときに参照する感じでまずはよいでしょう。
srcでリスト指定するということ
src
には複数の値をカンマ区切りで指定できます。これは「まずローカルにそのフォントがあればそれを使うとして、無ければWebのフォントを参照する」というように指定ができます[1]。まあ組版よりもWebでの用途ですね。
src: local('The Font'), url(<url:of:the:font>);
font-*
系のdescriptorに注意
先程font-family
でフォント名を用意しました。@font-face
では、「フォントの使われ方」を指定するものが幾つかあります。
@font-face { /*A*/
font-family: 'myfont';
src: local('Noto Serif JP');
font-width: condensed; /* font-stretchからrenameしたので、非対応処理系ではfont-stretchを指定する */
font-weight: 400;
font-style: italic;
}
body {
font-family: myfont;
}
これらの指定時、myfont君が長体で太字で斜体になるのか? なりません。
上の指定はスタイル指定側で
body {
font-family: myfont;
font-width: condensed;
font-weight: 400;
font-style: italic
}
を指定したとき/A/のフォントを適用する、という意味になります。では長体をかけたいときには? src
に長体用のフォントを指定するのが正道です。
@font-face { /*A*/
font-family: 'myfont';
src: local('Noto Serif JP');
}
@font-face { /*A condensed*/
font-family: 'myfont';
src: local('Noto Serif JP Condensed');/* Noto Serif JP Condensed という長体フォントがあるとする */
font-width: condensed;
}
p {
font-family: myfont;
font-width: condensed;
/* p でNoto Serif JP Condensedが使われる */
}
unicode-range
とsize-adjust
混植の本命ここまで最初に提示した「合成フォント」の課題解決とは関係ない話でした。
- (このケースでは)1番目のフォントが2番目のフォントが適用されてほしい字形を持っていてはいけない
- フォント同士の大きさの調整をどうする
これらを実現するのがunicode-range
とsize-adjust
です。
実は以前の記事で見せたテキストはかな漢字混植(かなと漢字が別フォント)です。
これを実現するのは次のCSSになります。
@font-face {
font-family: "Main";
font-style: normal;
src: local("FOT-筑紫オールド明朝Pro");
unicode-range: U+3000-303F, U+3100-FFFF;
}
@font-face {
font-family: "Main";
font-style: normal;
src: local("FOT-筑紫B明朝NKL");
unicode-range: U+3040-30FF;
size-adjust: 0.95;
}
:root {
--main-font-family: "Main", "Noto Serif JP", serif;
font-family: var(--main-font-family);
}
FOT-筑紫B明朝NKLはかなフォントなのでunicode-rangeの説明としてはやや不適当(「本来漢字字形も持つフォントのかな部分だけを使える」的な話)ですが、まあよいでしょう。
unicode-range
は名の通り、Unicodeの番号(や文字を直接記述して)で範囲を指定し、srcと組み合わせることで「その範囲の文字についてはこのフォントのものを使用する」という指定ができます。
そして異なるフォントを合わせるときに大事なサイズ調整を、@font-face
ではsize-adjust
で行えます。これで、実際に使用時には"Main"
のようにフォント名を呼び出すだけで、サイズ調整済みの合成フォントが使えます。
終わりに
いかがでしたか? CSS Fonts Module Level 4の現在のドラフトは正直よく分かりませんでした。
アセンダーやディセンダーなど、紹介しなかったけれどまだまだ調整項目があるので、ゆっくり沼に浸りましょう。
10日の記事はメイユールさんの『Vivliostyleで脚注のスタイルを変更する』です。
-
通常のfont指定とは違って、字形の有無は関係なくフォントが見つかった時点でそのフォントに決定します ↩︎
Discussion