- フォントは Web サイトの印象に直結するため、一概にこれが良いとは言えない。
- 特にこれと言った指定がされていない場合は
font-family: sans-serifのみで良い。- Windows 11/10 では 2025 年のアップデートにより Noto Sans JP が標準搭載された。色々と問題があった游ゴシックの呪縛から解放されたのは大きい。
- Android はメーカーにより削除されている可能性はあるが、そうでない場合は原則的に Noto Sans CJK JP が適用される。
- Mac/iOS はヒラギノ角ゴ ProN が適用される。
- アップデートによるフォントの変更の懸念はあるものの、ディスクリシアの方々は UD デジタル教科書体などの読みやすいフォントを設定している可能性があるため、アクセシビリティの観点では
font-family: sans-serifの指定を推奨する。
- 総称フォントには
system-uiが存在するが、こちらは Windows 環境では Noto Sans JP ではなく游ゴシックのUI書体がこんにちはするので注意。日本語環境では避けたほうが無難である。- 海外製のUIフレームワークやリセットCSSでは
system-uiが適用されている場合があるので注意する。特にTailwind CSSではフォントの設定を怠るとsystem-uiが適用されるので気をつけること。
- 海外製のUIフレームワークやリセットCSSでは
- デザインで Noto Sans JP が使用されている場合は、デバイスフォントを尊重して良いかデザイナーに確かめた方が良い。全デバイスで Noto Sans JP を表示するというオーダーを受けた際は Windows と Android で重複して読み込まれないように以下のように指定すること。(参考}
/* @font-face を利用してローカルフォントを優先させる */
@font-face {
font-family: 'Local Noto Sans JP';
src:
local('Noto Sans JP'), /* Windows */
local('Noto Sans CJK JP Regular') /* Android */;
}
:where(:root) {
font-family: "Local Noto Sans JP", "Noto Sans JP", sans-serif;
}- 明朝体を使用する場合は Android 端末だとメーカー側で明朝体そのものが削除されている可能性があるため、Noto Serif JP などの Web フォントの利用を検討する。
- なお、Noto Serif JP は Windows 11 には搭載されているものの、10 には搭載されていない。
- Noto Serif JP も同様に
@font-faceを利用してローカルフォントを優先させるようにする。
- 下のような指定を
:rootに指定しておく。
:where(:root) {
overflow-wrap: anywhere; /* 収まらない場合に折り返す */
/* word-break: initial; 単語の分割はデフォルトに依存(初期値のため指定しなくて良い) */
line-break: strict; /* 禁則処理を厳格に適用 */
}- 参考:文章の折り返し指定のCSS最新版 - ICS MEDIA
- kiso.cssを採用している場合は定義されているので不要である。
<em>や<cite>といった要素は通常イタリック体(斜体)で表示されるが、日本語において斜体は一般的に使用されない。<em>は「強調」を意味するが、日本語における強調は多くの場合は太字で表現される。- 以下は kiso.css で定義している日本語向けのリセット。kiso.css を採用しない場合は以下のような指定を行うようにする。
:where(em:lang(ja)) {
font-weight: bolder;
}
:where(:is(address, i, cite, em, dfn):lang(ja)) {
font-style: unset;
}- デフォルトで斜体表示される要素のうち、数式やプログラムコード内の変数の名前を表す
<var>は除外している。
- 原則的にはキーワードではなく数値指定を優先する。(参考)
- そのうえで
--font-bold: 700のようにデザイントークンとして変数化する。 - kiso.css では UA スタイルシートと合わせるためにキーワードを使用しているため、適宜 base レイヤーで上書きを行う。
text-align: centerを指定する場合は、後述するtext-wrap: balanceとセットで指定する。text-align: justifyはラインボックスの端に揃うように間隔が空けられるため段落を美しく表示するために便利であるように思えるが、英語などが含まれた際に一気に表示が崩れるリスクがあるため指定は原則禁止とする。text-align: justifyの揃え方を決定する text-justify が Chrome でサポートされるものの、先述した問題の解決策にはならない。text-align-last: justifyはテーブル見出しを均等割にする際に便利である(参考)。しかし、単一行であることが条件であるため、改行しないように工夫する必要がある。
- テキストの行の折り返し方法を指定するプロパティ。
- 基本的に明示する値は
prettyorbalanceの 2 択で、balanceではすべての行が同じくらいの長さになるように調整されるのに対して、prettyは最後の行が一つの単語だけで終わることを防ぐ。 - 英語では最後の行に一つだけ配置された単語を widows and orphans と呼び、テキストが読みにくくなるとして避けるべき対象とされている。そのため、
:lang(en)の場合はテキスト全体にprettyを指定するのが良い。 - 英語の見出しの場合はbalance を指定するのが美しいという見解もある。もっとも全ての英語の見出しが
balanceが最適とは限らないため、kiso.css ではprettyとし、ベースでbalanceを指定する方針とする。 - 日本語では本文はベタ組みにすることが原則であるため、段落に
text-wrapの措定は行わない。見出しの引き締めには貢献できるので、text-alignがstartorendならpretty、centerならbalanceを指定するのが良い。 - しかし、現在の Safari では日本語におけるそれの挙動がバグっている(
balanceと似たような動作をする)ため、日本語の場合はtext-wrap: prettyの指定をしないほうが良い。Safari のバグが修正されたら指定することを推奨する。
:where(:is(h1, h2, h3, h4, h5, h6, caption):lang(en)) {
text-wrap: balance;
}
:where(p:lang(en)) {
text-wrap: pretty;
}
.-text-center {
text-align: center;
text-wrap: balance;
}- kiso.cssでは現在は英語のみ適用している。
font-feature-settings: 'palt'で文字詰めができるが、日本語では本文はベタ組みにすることが原則であるためデフォルトでは指定しない。- 見出しに関しては文字詰めを行ったほうが可読性が向上するので指定を行う。
:where(h1, h2, h3, h4, h5, h6, caption) {
&:lang(ja) {
font-feature-settings: "palt";
}
}- 縦書きの場合は
paltだと文章全体が横にズレてしまうのでfont-feature-settings: "vpal"とする。
- フォントの特定のスタイルや装飾を制御することができるプロパティ。
- 原則的には
font-feature-settingsの上位互換であるが、使用頻度の高い'palt','pkna'に代わる方法が提供されていないので使い所は限られる。 - 文字を可変幅で表示する
font-feature-settings: pwidを使用する場合は、上位互換となるfont-variant-east-asian: proportional-widthを指定するようにする。 - 数字リストやローディング、料金テーブルのように数字を目立たせる箇所では
font-variant-numeric: tabular-numsを指定して数字の幅を均等にするのに用いると良い。
.-tabular-nums {
font-variant-numeric: tabular-nums;
}- プロポーショナルフォントの文字間隔を、隣り合う文字の組み合わせによって文字詰めすることを「カーニング」と呼ぶが、メトリクスカーニングと呼ばれる方法で、カーニングを制御するプロパティ。
- 初期値は
autoでブラウザ側に委ねられる。 - 日本語の場合は本文はベタ組みにすることが原則であるため、
font-kerning: normalの適用は可読性を悪化させる原因となる。基本的には見出しに利用し、デフォルトではnoneにしておく。 - 英語の場合はカーニングがあったほうが可読性は上げるため、デフォルトで
normalを指定する。
:where(:lang(en)) {
font-kerning: normal;
}
:where(:lang(ja)) {
font-kerning: none;
}
:where(h1, h2, h3, h4, h5, h6, caption) {
font-kerning: normal;
}<hgroup>内の<p>など、見出し以外にもカーニングさせたい要素がある場合に備えてfont-feature-settings: 'palt'と併せてユーティリティクラスも用意しておくと良い。
.-kerning {
font-kerning: normal;
&:lang(ja) {
font-feature-settings: "palt";
}
}- 日本語のなどの文字と英数字の間にスペースを入れるかどうかを制御するプロパティ。
- Web に関しては原則的に日本語のと英数字の間にスペースを入れるのが可読性が高くなるとされており、デフォルトで
text-autospace: normalを指定するのが良い。 - ただし、以下の要素については
text-autospace: no-autospaceを明示する。- 等幅フォントでずれる可能性がある→
<pre> - 慣習的に日付表記には空白は入らないため、日付表記に用いられる要素→
<time> - ユーザーが入力する要素では自動挿入が入ると挙動不審になる恐れがある→
<input><textarea>[contenteditable]
- 等幅フォントでずれる可能性がある→
:where(:root) {
text-autospace: normal;
}
:where(pre, time, input:not([type="button" i], [type="submit" i], [type="reset" i]), textarea, [contenteditable]) {
text-autospace: no-autospace;
}- kiso.cssを採用している場合は定義されているので不要である。
- 約物(句読点や括弧など)とそれ以外の文字との間のスペースを制御するプロパティ。現状は Chrome のみ。
- 通常の Web の文章は段落を字下げすることはなく、かつ見出しの最初の括弧の空白を消すほうが審美性に優れているためデフォルトでは
text-spacing-trim: trim-startを指定する。 - ただし、
pre要素はズレる可能性があるため、継承されないようにし、ズレないことを保証するためにtext-spacing-trim: space-allを明示する。
:where(:root) {
text-spacing-trim: trim-start;
}
:where(pre) {
text-spacing-trim: space-all;
}- kiso.cssを採用している場合は定義されているので不要である。
- デフォルトの
line-heightはアクセシビリティの観点から 1.5 以上とする。 - 原則的に単位なしの number として定義する。
- その上で各見出し、段落において適切な
line-heightを適用する。デザインに従うが、大体次のような行間が読みやすい。(参考)- 段落 → 和文は 1.7 〜 2、英文は 1.5 〜 1.8
- 見出し → 和文は 1.25 〜 1.5、英文は 1.2 〜 1.4
line-heightは命名をtightsnugnormalrelaxedlooseをベースにデザイントークンとして変数化する。- 改行した際に著しく表示を損ねることから line-height: 1 は指定を禁止とする( Stylelint で弾く)。デザイン上 1 とされている箇所は後述する
text-box-trim / text-box-edgeなどを用いてハーフレディングを取り除く方針にする。
- ハーフレディングを除去するプロパティ。
text-box-trimはテキストコンテンツの上端と下端のどちらを切り取るかを指定する。trim-startは上端、trim-endは下端、trim-bothは両方。- ハーフレディングを除去する目的なら
trim-both、ハーフレディングの除去は無くていいけど横並びになった画像と見出しの上端を合わせたい…というケースではtrim-startを指定するケースが多い。
- ハーフレディングを除去する目的なら
text-box-edgeは切り取る空間の大きさを指定する。既定値はtextで、上部をtext-over baseline、下部をtext-under baselineの位置でトリミングする。- 原則的には英文は
cap alphabeticで上端を X の上限、下端を x の下限でトリミングするのが良い。しかし、日本語の場合は詰まりすぎる場合があるので既定値のtextが良い。 - 切り取る空間の大きさはフォントに依存する。フォントによっては
textだと多少のアキが発生する。厳格に除去したいのであればmargin-block: calc((1em - 1lh) / 2)で詰めるのを推奨する。
- 原則的には英文は
- 先述したように
line-height: 1の代替手段としても使用する。 - Figma の場合はハーフレディング込みで余白が算出される(ハーフレディングを切り取る定義がされていない場合)が、 Adobe 製のツールはハーフレディングを含まずに余白が算出される。 Adobe 製のツールでカンプが作成されている場合は全称セレクタですべての要素に適用するのも選択肢。
- 現状では Firefox のみ非サポートであるが、ハーフレディングの有無で表示が著しく変化する or 崩れるとかでなければプログレッシブ・エンハンスメントで対応する方針。
.-trim-both {
text-box-trim: trim-both;
&:lang(en) {
text-box-edge: cap alphabetic;
}
}- インライン軸に句読点を包括できる余白が存在するのが条件だが、
hanging-punctuation: last allow-endの指定で「段落最後の閉じカッコ」と「行末の句読点」がぶら下がるようにできる。現在は Safari のみだが、そのうち Chrome にも来る予定である。 - 行頭や行末に位置する約物文字(句読点や括弧、引用符など)を行ボックスの外側にぶら下げることは、行揃えを改善するために有効である。印刷組版では、段落の開始引用符「“」や行末の句点「。」を行の外側に出して、他の行と揃えを取る手法が用いられている。
- 原則的には段落でのみ適用する。
- 注意点としては、約物を行外に出すことでコンテナの論理幅からはみ出すため、場合によっては水平スクロールバーが出ることがある。インライン軸に
paddingとセットで指定したほうがいい。 - 英語の場合は
hanging-punctuation: first allow-end lastとする。(参考)
.-hanging {
hanging-punctuation: last allow-end;
&:lang(en) {
hanging-punctuation: first allow-end last;
}
}- 指定した行数でテキストを省略するプロパティ。ベンダープレフィックスなしの
line-clampは全コアブラウザでサポートされていないため、 flex のベンダープレフィックス版の指定display:-webkit-boxとflex-directionに価する-webkit-box-orientと合わせてベンダープレフィックス付きで指定する必要がある。 - そのままだと三点リーダー込でオーバーフローするので、
overflowプロパティではみ出した部分を非表示にする必要がある。この際、overflow-y: clipとすること。 先述したhanging-punctuationと組み合わせた時にoverflow: hiddenだと約物が切り取られ、overflow-y: hiddenだとX軸のoverflowはautoにマッピングされてスクロールバーが表示されるためである。- こういったイレギュラーを防ぐため、また Scroll-driven Animation や
position: stickyの動きを阻害しないためにも基本的にoverflow: hiddenではなくoverflow: clipを優先して使用する。 grid-template系のアニメーションのようなoverflow: hiddenでないと動作しないものでのみoverflow: hiddenは使用するようにする。
- こういったイレギュラーを防ぐため、また Scroll-driven Animation や
.-line-clamp {
display: -webkit-box;
overflow-block: clip;
-webkit-box-orient: block-axis;
-webkit-line-clamp: var(--line-clamp--limit, 3);
@supports not (overflow-block: clip) {
overflow-y: clip;
}
}- 日本語の見出しは文節区切りでの改行と可読性がよくなる。
word-break: auto-phraseで文節区切りでの改行を行うことができるが、Chrome 系のみ。- Safari or Firefox で文節区切りでの改行を行う場合は BudouX を導入する。しかし、導入コストはあるため Chrome 系のみ文節区切りでの改行を行い、その他は従来のままというプログレッシブ・エンハンスメントの考えを持つのも選択肢。
- 本文まで全て文節改行すると、段落内で妙な空行が生まれて可読性を悪化させるので避けること。見出し・キャプション・短文詩などは文節改行が望ましい典型例であり、そういった必要な箇所に限定して使うようにする。
word-break: auto-phraseを指定する場合はtext-wrap: balanceを指定すると、より美しい改行を行うことができる(参考)。
:where(h1, h2, h3, h4, h5, h6, caption) {
&:lang(ja) {
@supports (word-break: auto-phrase) {
word-break: auto-phrase;
text-wrap: balance;
}
}
}- ついでにカーニング同様ユーティリティクラスも別途用意しておく。
.-auto-phrase {
&:lang(ja) {
@supports (word-break: auto-phrase) {
word-break: auto-phrase;
text-wrap: balance;
}
}
}- 長い単語がすべて次の行へ送られると、その前後の行で不自然なスペースが生じてしまう。単語の途中で改行しつつ、不自然にならない音節の位置にハイフンを挿入して改行する処理のことを「ハイフネーション」と呼ぶ。
hyphens: autoを指定することで、自動的に単語の途中でハイフネーションを行うことができる。- 注意点としては
hyphens: autoは言語依存のため、lang="en"属性などを付与して現在の言語を明示化する必要がある。
<div class="-hyphens" lang="en">
<p>You think that's where it's at</p>
<p>But is that where it's supposed to be?</p>
<p>You're getting it all over me, ex-rated</p>
</div>.-hyphens {
hyphens: auto;
}- テキストを大文字表記にする
text-transform: uppercaseが最も使用される。 - VoiceOver では略語として定義されているものはアルファベット毎に読み上げる(例:IT→「アイティー」、ADD→「エーディーディー」)ので、読み間違いを防ぐために依然としてこのテクニックは重要。
- ただし、CSSで各セレクタ毎に指定すると「全て大文字」とそれ以外が入れ込んだ時に辛いのでユーティリティクラスとして定義しておく。
.-uppercase {
text-transform: uppercase;
}- テキストの字下げを行うためのプロパティ。とは言え、
text-spacing-trimで触れたように通常の Web の文章は段落を字下げすることはない。 - 多くの場合は注釈の「※」のように逆方向に字下げをする場合に用いる。
- 従来は
padding-inline-start: 1em; text-indent: -1emのようにpaddingとセットで指定することが多かったが、現在は先頭行以外のすべての行を字下げするhangingキーワードが追加されているのでこちらを使用する。(参考)- Safari, Firefox は既にサポートされ、Chrome は 146 でサポートされる予定である。字下げがなくても表示に影響は無いためプログレッシブ・エンハンスメントで良い。
- 注釈をマークアップする際は note role を指定する。
- 注釈リストをマークアップする場合は
<ul><li>の暗黙的なロールを消さないように<div>でラップしてそれに指定する。 - 単一の注釈には
<p>要素に指定する。
- 注釈リストをマークアップする場合は
<p role="note">単一の注釈として表示する際のサンプルです。実際の表示・挙動は環境や設定により異なる場合があります。あらかじめご了承ください。</p>
<div role="note">
<ul>
<li>リストとして表示する際のサンプルです。実際の表示・挙動は環境や設定により異なる場合があります。あらかじめご了承ください。</li>
<li>記載の情報は作成時点のものです。最新の内容は公式情報をご確認ください。</li>
<li>本資料に含まれる数値・表現は仮のものです。正式な値は確定次第更新されます。</li>
</ul>
</div>:where(p[role="note"], [role="note"] li) {
text-indent: hanging 1em;
&::before {
content: "※";
}
}font-sizeをメディアクエリ or コンテナクエリで切り分けるのは辛いのでclamp()関数を使って最小値〜最大値の範囲でフォントサイズを滑らかに変化させるようにする。- ただし、推奨値の計算を CSS のみで行うのも辛い。
progress()関数もしくは CSS 標準の@functionが広まればこのあたりは改善するが、現状では厳しい。 - オンラインジェネレーターで算出するのは行き来するコストが掛かり、コメントを残さないと推奨値の計算手順が分からない、といった理由からなるべく避けたほうがいい。
- Sass を使ってるなら自前の
@functionを作成するようにする。CSS 標準でやりたいならユーティリティクラスを作ってカスタムプロパティを受け渡しできるようにすると良い。 - サイト全体の調和を優先するなら
svi、コンポーネント毎にスコープを切り分けるならコンテナクエリ +cqiのように相対先の単位を出し分けできるようにしておく。
.-fluid-text {
--_u-relative-max-width: var(--fluid-text--relative-max-width, 1280);
--_u-relative-min-width: var(--fluid-text--relative-min-width, 375);
--_u-min-font-size: var(--fluid-text--min-font-size, 14);
--_u-max-font-size: var(--fluid-text--max-font-size, 16);
--_u-base-font-size: var(--fluid-text--base-font-size, 16);
--_u-relative-unit: var(
--fluid-text--relative-unit,
100svi
); /* 100svi or 100cqi */
/* slope and intercept calculations */
--_u-fluid-slope: calc(
(var(--_u-max-font-size) - var(--_u-min-font-size)) /
(var(--_u-relative-max-width) - var(--_u-relative-min-width))
);
--_u-fluid-intercept: calc(
var(--_u-min-font-size) - var(--_u-fluid-slope) *
var(--_u-relative-min-width)
);
font-size: clamp(
var(--_u-min-font-size) / var(--_u-base-font-size) * 1rem,
var(--_u-fluid-slope) * var(--_u-relative-unit) + var(--_u-fluid-intercept) /
var(--_u-base-font-size) * 1rem,
var(--_u-max-font-size) / var(--_u-base-font-size) * 1rem
);
}- コンポーネントのローカルカスタムプロパティや API 的カスタムプロパティとのバッティングを防ぐために、 API 的に受け取る用のカスタムプロパティと内部カスタムプロパティを分離しつつ、ローカルには
_u-、API にはfluid-text--プレフィックスを付与する。 sviはviやlviでも問題ないケースが殆どだと思うが、cqiは基準コンテナが見つからない場合にsviを返すという仕様があるため、それと合わせている。
- 今までは
rem指定が有効に働くケースは Chrome の文字拡大機能(not ズーム機能)のみであり、「誰が使ってるか分からないマイナーな機能をサポートするコストが見合わない」「Chrome がpxでも文字拡大できるようにすればいい」といった意見にも賛同できるところがあったため「どっちでもいい」というスタンスを取ってきたが、<meta name="text-scale" />の登場によって考えが変わった。(参考) text-scaleが有効な場合、OS の文字スケール設定とブラウザの文字スケール設定の両方に比例してフォントサイズが拡大・縮小される。すべてのデバイスにおいて OS レベルの文字スケール設定を尊重する簡単な方法は存在しないから、remとかem使って実装してるサイトであればそれを OS レベルの文字スケール設定として再定義すればいいのでは?って感じらしい。pxでは動作しないことが(Draft段階であるものの)仕様にも書かれている。- 単純に「
remが常に正解」「pxはダメ」というような二者択一ではない。全てをremで定義するのはズーム機能との棲み分けができていない。 pxorremは「この値はユーザーがデフォルトフォントサイズを大きくしたとき、一緒に大きくなるべきか?」 を使い分けの基準にすべき。- テキストサイズ、段落の垂直マージン、行間などはフォントサイズと連動させた方がいいので
remなどを使う。 - 一部装飾的な境界線幅、細かいデザインディテールなどは文字拡大に伴って大きくなっても嬉しくないので
pxを使う。 - テキストを含むコンテンツの幅やメディアクエリやコンテナクエリのブレイクポイントは文字拡大時に窮屈になったりレイアウトが崩壊する可能性があるから
remなどを使った方がいい。 - 水平方向の
paddingは文字サイズと連動すると一行あたりの文字数が減り、可読性を落とす可能性があるのでpxを検討する。
- テキストサイズ、段落の垂直マージン、行間などはフォントサイズと連動させた方がいいので
- 重要なことはremを使う以上ブラウザの文字拡大機能を有効にして検証すべきだということ。アクセシビリティ重視のために
remを使いましょうと言いつつ、:rootにfont-size: 10pxなどの固定値を指定する実装をたまに見かけるが、文字拡大機能を有効にして検証すれば動いていないことは明白であるはず。「font-sizeにはremを使う」というルールが独り歩きして肝心なことを見落としている。
- 余談であるが、メディアクエリやコンテナクエリのブレイクポイントには
calc()やmax()などの数学関数が利用できる。 - ブレイクポイントを
remやemに変換する場合は@media (width >= calc(768 / 16 * 1em))のように指定したほうが計算機を使う手間が省け、元のピクセル値がわかりやすくなるメリットがあるので推奨する。- メディアクエリはビューポートを基準とするため、メディアクエリの中ではブラウザの文字サイズを基準に計算される。そのため、
remもemもフォントサイズの変更が行われていない場合は16px相当になる。 - コンテナクエリの場合は
container-type: inline-sizeを指定した要素のフォントサイズを基準として計算される。
- メディアクエリはビューポートを基準とするため、メディアクエリの中ではブラウザの文字サイズを基準に計算される。そのため、
- 各見出しにおいて手動で改行を行う場合は、ポエムなどの文章構造的に意味のある改行以外では
<br>は使わずに CSS で改行制御を行う。 - 原則的には
display: inline flow-rootを指定した<span>要素か、親要素にdisplay: block flex+flex-wrap: wrapを指定するようにする。 - 手動改行は多くのケースでは日本語都合であるため、
:lang(ja)の時のみ上記のアプローチを行い、その他の言語では「<span>そのものを無いもの」とする方針にする。 - 段落上の手動改行は
word-break: auto-phrase同様に可読性を悪化させる可能性があり、特にレスポンシブとの相性が悪いので避ける。デザイン上の改行が行われている場合はデザイナーに掛け合って「無理です」と伝えた方が良い。
.-br {
display: contents;
&:lang(ja) {
display: block flow;
}
}
.-wbr {
display: contents;
&:lang(ja) {
display: inline flow-root;
}
}文章によっては改行によって分割されると不都合なワードも存在する。
分割させたくない文字と文字の間には「‍(zeroゼロ width幅 joiner接合子)」を挿入することで分離禁止な単語として明示することができる。
<p>marginが相‍殺するのを防止するために、なるべくmarginの向きは上方向に統一しておきます。</p>上記のケースでは「相殺する」の「殺」が頭に来ると不穏な言葉が生まれてしまうので、それを防止している。
- リセット CSS には kiso.css を採用しているのを前提とする。採用しない場合は kiso.css から該当箇所をコピペして base レイヤーに指定する。
- base レイヤーには次のような記述を記述を行う。
:where(:lang(en)) {
font-kerning: normal;
}
:where(:lang(ja)) {
font-kerning: none;
}
:where(h1, h2, h3, h4, h5, h6, caption) {
font-kerning: normal;
&:lang(en) {
text-wrap: balance;
}
&:lang(ja) {
font-feature-settings: "palt";
@supports (word-break: auto-phrase) {
word-break: auto-phrase;
text-wrap: balance;
}
}
}- reset レイヤーには次のような記述を行う。
.-fluid-text {
--_u-relative-max-width: var(--fluid-text--relative-max-width, 1280);
--_u-relative-min-width: var(--fluid-text--relative-min-width, 375);
--_u-min-font-size: var(--fluid-text--min-font-size, 14);
--_u-max-font-size: var(--fluid-text--max-font-size, 16);
--_u-base-font-size: var(--fluid-text--base-font-size, 16);
--_u-relative-unit: var(
--fluid-text--relative-unit,
100svi
); /* 100svi or 100cqi */
/* slope and intercept calculations */
--_u-fluid-slope: calc(
(var(--_u-max-font-size) - var(--_u-min-font-size)) /
(var(--_u-relative-max-width) - var(--_u-relative-min-width))
);
--_u-fluid-intercept: calc(
var(--_u-min-font-size) - var(--_u-fluid-slope) *
var(--_u-relative-min-width)
);
font-size: clamp(
var(--_u-min-font-size) / var(--_u-base-font-size) * 1rem,
var(--_u-fluid-slope) * var(--_u-relative-unit) + var(--_u-fluid-intercept) /
var(--_u-base-font-size) * 1rem,
var(--_u-max-font-size) / var(--_u-base-font-size) * 1rem
);
}
.-text-center {
text-align: center;
text-wrap: balance;
}
.-trim-both {
text-box-trim: trim-both;
&:lang(en) {
text-box-edge: cap alphabetic;
}
}
.-kerning {
font-kerning: normal;
&:lang(ja) {
font-feature-settings: "palt";
}
}
.-auto-phrase {
&:lang(ja) {
@supports (word-break: auto-phrase) {
word-break: auto-phrase;
text-wrap: balance;
}
}
}
.-hanging {
hanging-punctuation: last allow-end;
&:lang(en) {
hanging-punctuation: first allow-end last;
}
}
.-uppercase {
text-transform: uppercase;
}
.-hyphens {
hyphens: auto;
}
.-line-clamp {
display: -webkit-box;
overflow-block: clip;
-webkit-box-orient: block-axis;
-webkit-line-clamp: var(--line-clamp--limit, 3);
@supports not (overflow-block: clip) {
overflow-y: clip;
}
}
.-br {
display: contents;
&:lang(ja) {
display: block flow;
}
}
.-wbr {
display: contents;
&:lang(ja) {
display: inline flow-root;
}
}
人の gist に唐突に横槍すみません、間違いの指摘ではありませんが、状況を共有したく… 🙇
詰め組みは
paltだけでなくkernを併用して実現することがほとんどです。font-kerning: normalはkern相当の意図かと思われますが、Firefox では日本語(CJK)ではkern無効です。(
font-kerning: normalで日本語にkernだけが効くこと自体があまり意図しない挙動です)また、縦組みでは
vpal,vkrnになることに注意が必要です。余談ですが、まだ使われていませんが、OpenType 1.9.1 で
apkn,vapkが 入りました。縦組みや
apknなどの経緯により、詰め組みは将来的(遠い先の話)にfont-feature-settingsではなく、font-kerningで解決するほうが望ましいように思います。釈迦に説法かと思いますが、
lang="ja"でfont-kerning: noneにすると、文字種によらず Kerning が OFF になり、欧文中のカーニングも効きません。en環境下でnormalを利用するのは良いともいますが、ja環境下でnone | normalどちらにするかは、日本語のベタを優先するか、欧文の kerning を優先するかになるかのトレードオフになるのが現状かと思います。ちなみに、今のところ、詰め組みは
font-kerning: always / allのようなものが議論されており、font-kerning: normal=> 日本語ベタ・欧文詰め(kern)font-kerning: always / all=> 日本語詰め (palt + kern)・欧文詰め(kern)のように整理されるかもしれません。(だいぶ先だと思いますが…)
重箱の隅かつ指摘でもなく恐縮ですが、共有まで。