読みやすい文章にするためにはどうしたらいいか。

経緯

前回フォントサイズ調整して読みやすくしようとした。でもその方法が本当に正しいのか疑問だったので少し調べた。

タイポグラフィ考慮点

  • 対象言語
    • 日本語、英語
    • 一字あたりの情報量(英日1:2.5)
    • 音節あたりの情報量(英日1:0.69)
  • 記憶量
    • 一文あたり最大60字までが認識限界
    • 一文あたり句読点が3つ以上あると長く読みづらくなる
  • 字数
    • 一行あたり35〜40字程度が読みやすいとされている
      • 横書き:35〜38字
      • 縦書き:38〜40字
      • 文庫本:38〜42字(14〜18行/頁。532〜756字/頁。8〜12万字/冊)
  • 字種
    • 漢字3割ひらがな7割がよいとされる
  • 読む速さは400字/分と言われている
    • ニュース記事は大体500〜600字
  • 余白
    • 行間:1.5〜1.75em
    • 字間:0.05〜0.1em
    • カーニング(字間詰め)
      • 記号
      • フォントサイズが大きい見出し
  • 作文術
    • 実用文
      • 書式
        • SDS法
        • PREP法
        • DESC法
        • 穴埋め文章作成法
      • パラグラフライティング
    • 創作文
      • 書式
        • 三幕構成
      • 修辞法

考えることが多すぎる。要点だけ絞ったのに。

作文術に至ってはタイポグラフィではない。なんと分類すればいいかわからないが、読みやすい文章を作るために必要な要素なのでここに書いておく。

情報源

みてみた

Wikipediaタイポグラフィのページを私の環境でみると一行あたり64字だった。たしかに長すぎて読みづらい。また、一文あたり句読点が3つ以上ある文も頻出する。私が言えたことではないが、まさに悪文の見本市。

ほかの情報源をみると、一行あたりの字数は37、44、50などだった。40字以下なら読みやすいかというと、そうでもなかった。2K(1920x1080)ディスプレイで閲覧したとき、以下のようなことが気になった。

  • 余白が大きすぎる
  • 文字が小さすぎる
  • サイトの画面構成が2カラムになっていてサイド部分は19字だった

ディスプレイは横に広いのに、文字は中央のごく狭い範囲に集中している。スクロール数も増える。だったらそのムダに広い余白をもっと有効利用できないのかと思ってしまう。

そこで画面サイズに応じてフォントサイズを変えたらいいのでは? と思いつき以下のようにした。

:root {
    --line-of-chars:35;
    --font-size:calc(100vw / (var(--line-of-chars)));
    --line-height:1.5em; /*1.5〜1.75em*/
    --letter-spacing:0.05em; /*0.05〜0.1em*/
}
@media screen and (max-width: 959px) {
    --line-of-chars:30; /* 〜32px/字 */
}
@media screen and (max-width: 480px) {
    --line-of-chars:20; /* 〜24px/字 */
}
body {
    font-size: var(--font-size);
    line-height: var(--line-height);
    letter-spacing: var(--letter-spacing);
}

でもこれ、窓をリサイズしても変更されない。窓サイズでなく画面サイズ基準だから。元から画面が小さいスマホではいつも最大表示だろうしそれで問題ないと思うが。

余白大・文字小問題

どうしてこうなった?

これはフォントサイズというより画面アスペクト比の問題かもしれない。

日本語の全角字はほぼ横縦1:1である。正確にはやや縦長か。半角英数字に至ってはほぼ横縦1:2であり縦長である。幅が半分なので2文字にすればほぼ1:1と言える。いずれにせよ字は縦長の傾向にある。

それに対してディスプレイは横縦16:9が主流になった。横長である。もし一行あたりいくら書いても読みづらくならないなら問題なかった。しかし一行あたり40字くらいが読みやすさの上限であるなら、せっかくの横長ディスプレイを生かせない。だから世の中にはムダな余白まみれのサイトであふれているのだろう。

もしこれをフォントサイズ増大で解決しようとしても無駄である。なにせフォントの横縦比が1:1または1:2だとしたら横より縦のほうが多く増えるから。画面比は横縦16:9であり、縦のほうが少ないため縦のほうが速く消費されてしまう。1字あたりの横縦比1:1、画面比16:9、両者かけあわせて横長である。比1:1のフォントサイズを変更しても画面比は変わらない。よってこの問題を解決するのにフォントサイズ変更は使えない。

対象 横縦比
1:1(やや縦長?)
画面 16:9
文書 40:N(文量・行間・font-size等によるが800字(20行)超で縦長になる?)

どうすればいい?

段組みする。新聞のように。画面を分割してアス比を変える。

横長ディスプレイなら縦中央で2分割する。16:9なら8:9が2つできる。もし2K(1920x1080)なら1面あたり960px(1920/2)である。1字あたり16px以上であることを期待するなら60字(960/16)分のサイズがある。ここから余白や字間、サイドメニューを差し引いて本文が35〜40字になるくらいの幅にすればよいだろう。

ただし画面分割はディスプレイが一定の大きさでないと不可能。たとえば横幅320pxのスマホだと小さすぎて分割できない。正確には分割できるが最小フォントにしても左右一行あたり10字ずつになる。短すぎて読みづらくなるため不適切。

つまり画面サイズとアス比の両方を考慮した上で、画面分割するかしないか分岐し、両方のパターンを実装する必要がある。

でもそれはめちゃくちゃ大変。だからまずはフォントサイズの適正化からはじめる。

妥協案

CSS MediaQuery

今まではこれを実装していた。

:root {
    --line-of-chars:35;
    --font-size:calc(100vw / (var(--line-of-chars)));
    --line-height:1.5em; /*1.5〜1.75em*/
    --letter-spacing:0.05em; /*0.05〜0.1em*/
}
@media screen and (max-width: 959px) {
    --line-of-chars:30; /* 〜32px/字 */
}
@media screen and (max-width: 480px) {
    --line-of-chars:20; /* 〜24px/字 */
}
body {
    font-size: var(--font-size);
    line-height: var(--line-height);
    letter-spacing: var(--letter-spacing);
}

JavaScriptでフォントサイズを計算しCSSにセットする

前回は楽勝だろと思って実装してみたが、全然ダメだった。

とくに以下の2つに差異が出てしまうことをきちんと考慮できていなかった。

  • ユーザが思う理想値
  • ディスプレイや最小フォントサイズにより制限された実際値
      40{指定値}
        ▼
|-----------| {実際値}字/行
20         50
{最小値}  {最大値}

上記のように理想値をユーザがUIで指定し、ディスプレイサイズや表示領域に応じて最低値保障した実際値を表示するようにすることが必要だった。

けれど前回は以下のようなスライダーUIを作った。

|-----------| {指定値,実際値}/{最大値}字/行

最大値20字未満なら実際値20になる。そのときは20/12字/行のように最大値のほうが小さくなる。紛らわしい。

スライダーの最大値はディスプレイサイズや表示領域サイズによって変わるようにした。スライダーの最大値だけを可変にすればいいと思っていた。けれど実際はそれだとおかしなことになる。たとえばフォントサイズが16px以下、20字以下にならないように計算するが、実際に表示される一行あたりの字数は画面幅に応じて20字未満になってしまう。たとえば画面幅160pxなら160/16で10字/行となる。

計算

そうなるのは、以下を考慮したから。読みやすくするための基準値である。

  • 16px未満だと小さすぎて見えなくなる
  • 日本語は一行10字以下だと読みづらい
  • スマホでは一行20字である

とくに16px/字は最も重要。スマホのOSやブラウザによってはこれより小さく表示できない場合があるらしい。それに日本語は画数の多い漢字があるため、小さすぎると見づらくなる。よって16pxは死守すべき。

となると犠牲にできるのは一行あたりの字数になる。それでも日本語は一行あたり10字以下だと文章が読みづらくなる。スマホでは20字なのでそれを最低値とする。ただ、窓サイズを縮めるなどして表示領域を縮小するとそれより小さくなってしまう。

もし16px以上かつ20字/行の両方を実現するなら、窓サイズをそれ以上小さくできないようにすべき。

または最小字数のほうを小さくし、スライダーのmin,maxに反映させる。

つまり実際の表示とスライダー表示、最低保障値のすべてを満たすためには以下のいずれかの方法しかない。

  • 窓サイズの縮小制限(最低保証値分のサイズまでしか縮小できないようにする) minWidth
  • 一行あたり字数最低保証値の撤廃(窓を自由にリサイズできるが一行10字未満になり読みづらくなる)
  • 一行あたり字数最低保証値の撤廃(窓を自由にリサイズし一行20字(16px以上)を堅持するもスライダーの最大値が20未満になる)

320px未満の表示領域で利用することがないなら、窓サイズの縮小制限でよい。

320px未満の表示領域で利用することがあるなら、一行あたり字数最低保証値の撤廃をする。

スライダーの最小・最大値

どのように決定すべきか。

  1. 理想値
  2. 最低保障値
  3. 実際値
項目 N字/行 font-size-px
最大上限値 50 -
理想値 35 -
最低保障値 - 16
実際値 1〜 16〜
  • 実際のディスプレイサイズが理想値より小さい
  • 実際の表示領域が理想値より小さい

ディスプレイサイズに応じて最大値を算出すべきでは? 640pxなら640/16=40字/行など。最小値16pxなのだから最大値はディスプレイ×最小値で算出できる。一行あたりの最大字数=Math.min(50, Math.floor(Display.width / 16))

50はどんな出版物であっても大抵は50以下らしいことから固定値にした。

付録

CSS

フォント

CSSプロパティ 意味
font-size 大きさ(大文字)
font-size-adjust サイズ比(大文字に対する小文字の比)
font-stretch 横幅比
font-family フォントの種類
font-width 太さ
font-style 斜度
font-variant 変化形
  • フォント
    • font-size:サイズ
    • font-family:ファミリ
    • font-width:幅
    • font-style:書体(itaric)