Skip to content

Instantly share code, notes, and snippets.

@tak-dcxi
Last active June 8, 2025 13:26
Show Gist options
  • Select an option

  • Save tak-dcxi/0f8b924d6dd81aaeb58dc2e287f2ab3a to your computer and use it in GitHub Desktop.

Select an option

Save tak-dcxi/0f8b924d6dd81aaeb58dc2e287f2ab3a to your computer and use it in GitHub Desktop.
タイポグラフィCSS

タイポグラフィ

汎用的な文章の折り返し指定

  • 下のような指定を:rootに指定しておく。
:where(:root) {
  overflow-wrap: anywhere; /* 収まらない場合に折り返す */
  /* word-break: initial; 単語の分割はデフォルトに依存(初期値のため指定しなくて良い) */
  line-break: strict; /* 禁則処理を厳格に適用 */
}

text-wrap

  • テキストの行の折り返し方法を指定するプロパティ。
  • 基本的に明示する値はprettyorbalanceの 2 択で、balanceではすべての行が同じくらいの長さになるように調整されるのに対して、prettyは最後の行が一つの単語だけで終わることを防ぐ。
  • 英語では最後の行に一つだけ配置された単語を widows and orphans と呼び、テキストが読みにくくなるとして避けるべき対象とされている。そのため、:lang(en)の場合はテキスト全体にprettyを指定するのが良い。
  • 日本語では本文はベタ組みにすることが原則であるため、段落にtext-wrapの措定は行わない。見出しの引き締めには貢献できるので、text-alignstartorendならprettycenterならbalanceを指定するのが良い。
  • あとはdisplay: inline flow-rootしたアイコンを含むテキストには、アイコンのみ折り返されることを防ぐためにprettyの指定を推奨する。
:where(:root) {
  &:lang(en) {
    text-wrap: pretty;
  }
}

:where(h1, h2, h3, h4, h5, h6) {
  text-wrap: pretty;
}

.text-center {
  text-align: center;
  text-wrap: balance;
}

font-feature-settings

  • font-feature-settings: 'palt'で文字詰めができるが、日本語では本文はベタ組みにすることが原則であるためデフォルトでは指定しない。
  • 見出しに関しては文字詰めを行ったほうが可読性が向上するので指定を行う。
:where(h1, h2, h3, h4, h5, h6) {
  &:lang(ja) {
    font-feature-settings: "palt";
  }
}

font-variant

  • フォントの特定のスタイルや装飾を制御することができるプロパティ。
  • 原則的にはfont-feature-settingsの上位互換であるが、使用頻度の高い'palt', 'pkna'に代わる方法が提供されていないので使い所は限られる。
  • 基本的には数字リストやローディング、料金テーブルのように数字を目立たせる箇所ではfont-variant-numeric: tabular-numsを指定して数字の幅を均等にするのに用いると良い。
.tabular-nums {
  font-variant-numeric: tabular-nums;
}

font-kerning

  • プロポーショナルフォントの文字間隔を、隣り合う文字の組み合わせによって文字詰めすることを「カーニング」と呼ぶが、メトリクスカーニングと呼ばれる方法で、カーニングを制御するプロパティ。
  • 初期値はautoでブラウザ側に委ねられる。
  • 日本語の場合は本文はベタ組みにすることが原則であるため、font-kerning: normalの適用は可読性を悪化させる原因となる。基本的には見出しに利用し、デフォルトではnoneにしておく。
  • 英語の場合はカーニングがあったほうが可読性は上げるため、デフォルトでnormalを指定する。
:where(:root) {
  &:lang(en) {
    font-kerning: normal;
  }

  &:lang(ja) {
    font-kerning: none;
  }
}

:where(h1, h2, h3, h4, h5, h6) {
  font-kerning: normal;
}

text-autospace

  • 日本語のなどの文字と英数字の間にスペースを入れるかどうかを制御するプロパティ。現状は Safari のみ。
  • Web に関しては原則的に日本語のと英数字の間にスペースを入れるのが可読性が高くなるとされており、デフォルトでtext-autospace: normalを指定するのが良い。
  • ただし、pre要素は等幅フォントでずれる、time要素は「2025 年」のような日付表記には空白が入らない、input要素やtextarea要素のようなユーザーが入力する要素では自動挿入が入ると挙動不審になる恐れがあるためtext-autospace: no-autospaceを明示する。
:where(:root) {
  text-autospace: normal;
}

:where(pre, time, input, textarea, [contenteditable]) {
  text-autospace: no-autospace;
}

text-spacing-trim

  • 約物(句読点や括弧など)とそれ以外の文字との間のスペースを制御するプロパティ。現状は 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;
}

hanging-punctuation

  • インライン軸に句読点を包括できる余白が存在するのが条件だが、hanging-punctuation: last allow-end の指定で「段落最後の閉じカッコ」と「行末の句読点」がぶら下がるようにできる。(Safari のみ)
  • 行頭や行末に位置する約物文字(句読点や括弧、引用符など)を行ボックスの外側にぶら下げることは、行揃えを改善するために有効である。印刷組版では、段落の開始引用符「“」や行末の句点「。」を行の外側に出して、他の行と揃えを取る手法が用いられている。
  • 原則的には段落でのみ適用する。
  • 注意点としては、約物を行外に出すことでコンテナの論理幅からはみ出すため、場合によっては水平スクロールバーが出ることがある。
.description {
  padding-inline: 1ic;
  hanging-punctuation: last allow-end;
}

文節区切りでの改行

  • 日本語の見出しは文節区切りでの改行と可読性がよくなる。
  • word-break: auto-phrase で文節区切りでの改行を行うことができるが、Chrome 系のみ。
  • Safari or Firefox で文節区切りでの改行を行う場合は BudouX を導入する。しかし、導入コストはあるため Chrome 系のみ文節区切りでの改行を行い、その他は従来のままというプログレッシブ・エンハンスメントの考えを持つのも選択肢。
  • 本文まで全て文節改行すると、段落内で妙な空行が生まれて可読性を悪化させるので避けること。見出し・キャプション・短文詩などは文節改行が望ましい典型例であり、そういった必要な箇所に限定して使うようにする。
:where(h1, h2, h3, h4, h5, h6) {
  &:lang(ja) {
    word-break: auto-phrase;
  }
}

https://github.com/google/budoux

hyphens

  • 長い単語がすべて次の行へ送られると、その前後の行で不自然なスペースが生じてしまう。単語の途中で改行しつつ、不自然にならない音節の位置にハイフンを挿入して改行する処理のことを「ハイフネーション」と呼ぶ。
  • hyphens: auto を指定することで、自動的に単語の途中でハイフネーションを行うことができる。
  • 注意点としては hyphens: auto は言語依存のため、 lang="en" 属性などを付与して現在の言語を明示化する必要がある。
<div 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;
}

手動改行

  • 各見出しにおいて手動で改行を行う場合は、ポエムなどの文章構造的に意味のある改行以外ではbrは使わずに CSS で改行制御を行う。
  • 原則的にはdisplay: inline flow-rootを指定したspan要素か、親要素にdisplay: block flex + flex-wrap: wrapを指定するようにする。
  • 手動改行は多くのケースでは日本語都合であるため、:lang(ja)の時のみ上記のアプローチを行い、その他の言語では「指定がないもの」とする方針にする。
.manual-br {
  display: contents;

  &:lang(ja) {
    display: block flow-root;
  }
}

.manual-wbr {
  display: contents;

  &:lang(ja) {
    display: inline flow-root;
  }
}

分離禁止の明示

文章によっては改行によって分割されると不都合なワードも存在する。

分割させたくない文字と文字の間には「‍(zeroゼロ width幅 joiner接合子)」を挿入することで分離禁止な単語として明示することができる。

<p>marginが相&zwj;殺するのを防止するために、なるべくmarginの向きは上方向に統一しておきます。</p>

上記のケースでは「相殺する」の「殺」が頭に来ると不穏な言葉が生まれてしまうので、それを防止している。

結論 

:where(:root) {
  text-spacing-trim: trim-start;
  text-autospace: normal;
  line-break: strict;
  overflow-wrap: anywhere;
  
  &:lang(ja) {
    font-kerning: none;
  }

  &:lang(en) {
    font-kerning: normal;
    text-wrap: pretty;
  }
}

:where(h1, h2, h3, h4, h5, h6) {
  font-kerning: normal;
  text-wrap: pretty;

  &:lang(ja) {
    font-feature-settings: "palt";
    word-break: auto-phrase;
  }
}

:where(pre) {
  text-spacing-trim: space-all;
}

:where(pre, time, input, textarea, [contenteditable]) {
  text-autospace: no-autospace;
}

.description {
  padding-inline: 1ic;
  hanging-punctuation: last allow-end;
}

.text-center {
  text-align: center;
  text-wrap: balance;
}

.hyphens {
  hyphens: auto;
}

.tabular-nums {
  font-variant-numeric: tabular-nums;
}

.manual-br {
  display: contents;

  &:lang(ja) {
    display: block flow-root;
  }
}

.manual-wbr {
  display: contents;

  &:lang(ja) {
    display: inline flow-root;
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment