CSSでバーティカルリズムを実現しよう!line-height-stepを使ってみる

「バーティカルリズム」(Vertical Rhythm)と呼ばれるデザイン手法があります。最近は関連記事も増えてきたので聞いたことがある、という方もいらっしゃるかもしれません。日本語本来のタイポグラフィでは「行取り」と呼ばれる類似の手法があり、ほぼ全ての印刷物やワープロで使われています。

「行取り」あるいは「バーティカルリズム」とは、要素の配置に一定のリズムを取り入れることで、デザイン上の安定感や、可読性の向上などの効果が見込るデザイン手法です。通常は、本文の行の高さをリズムの単位として、要素間の余白を調整します。ノートの罫線や、原稿用紙をイメージするとわかりやすいと思います。

上の例のように、CSSでline-heightmarginを適切に設定すれば実現可能ですが、メンテナンスが煩雑になる、レスポンシブにするのが難しい、見出しが複数行になるとうまくいかない、などの課題が残ります。

現在W3Cでは、この問題を改善するために、line-height-stepという新しいプロパティを議論しています。まだ異論や技術的課題が残っていますが、Chrome、Edge、Safariは賛同しており、Chromeでは試験運用機能として実装もされています。この記事では、このプロパティを使って、バーティカルリズムを実装する方法について解説します。

二つのスタイル:強いリズムと弱いリズム

まずは、どこにどのように適用するかを考えます。「バーティカルリズム」にもメリットとデメリットがあります。メリットとデメリットを理解して、適切に適用する方法を考えてみましょう。

一つ目のメリットは、行や要素が一定の間隔を持つことで、デザイン上の安定感が生まれることです。規則的に並んでいるデザインは、洗練、安定、安心、といった印象を与えます。

二つ目のメリットは、脳が一定のリズムをパターン認識することで、可読性を上げることです。目線が次の行頭に移動する時は、可読性が一番妨げられる時でもあります。脳が次の行頭位置を予測することで、目線の移動を助け、より早く、より楽に読めることで、内容の理解力も高まるとされています。

残念ながら、デメリットもあります。一つ目は、スペースを消費することです。余白を広げて調整するため、適用しない場合と比べて、より広いスペースが必要になります。モバイルでは画面の大きさが限られているため、本文の行の高さの半分をリズムの単位にするなどの工夫もあるようです。

デメリットの二つ目は、余白が一定でなくなることです。これはちょっとわかりにくいので、例を挙げて説明します。

画像や表、引用文、コード、コラムなど、大き目のブロックが入った場合を考えてみます。「バーティカルリズム」を適用するなら、これらのブロックの高さを本文行の高さの整数倍に揃えることになります。雑誌などデザイン重視の印刷物では、通常は画像や表の大きさを調整して揃えますが、Webでは画像のサイズを変えたくないため、余白で調整することになります。この結果、画像が複数ある時に、画像と本文の間の余白が一定にならない、という副作用が生まれます。

二つの画像の間に、一行の本文がある場合がわかりやすいかと思います。

一定のリズムを作るデザインを心がけているのに、この余白が一定で無いのは残念です。また、大きなブロックをまたいだ場合、上に挙げたメリットは小さくなってしまいます。脳が画像をまたいでパターン認識するのは困難ですし、目線が画像の次の行頭を見つけるのは簡単です。

この点から、大きな画像や表に対しては、画像をリサイズできない場合には「バーティカルリズム」を適用せず、余白を一定にする手法が一般的に使われる、と「日本語組版処理の要件」および、JIS X 4051「日本語文書の行組版方法」では定めています。

W3Cでの議論を見ると、この点が、英語圏由来の「バーティカルリズム」と、日本語本来の「行取り」では大きく違うようで、英語圏由来の「バーティカルリズム」は、余白の調整は断念し、常に適用する場合が多いようです。対して「日本語組版処理の要件」では、行取りの処理例は、見出しの説明の中でのみ出てきます。日本語は、文字の高さが一定のため、画像と本文の余白を、英語の場合よりも気にするのかもしれません。

本記事では、適用する場合と、空白を揃える場合の両方のパターンを使って、本文と見出しにのみ適用してみます。

CSSコーディング

提案中の line-height-step プロパティを設定すると、行の高さが設定値の倍数になるように切り上げられます。これを使って、CSSを書いてみましょう。便宜上、見出しは <h2><h3>、本文は <p>、画像やコラムは <div> タグを使っているとします。

line-height-step プロパティはまだChromeの試験運用機能でしか使えないので、まずは @supports で囲みます。ブラウザで表示を確認する場合には、Chromeのアドレスバーに「chrome://flags」と入力し、表示された画面で「Experimental Web Platform features」を有効にしてください。

日本語の行間は、フォントサイズの1.5倍から1.8倍くらいが読みやすいとされていますので、ここでは font-size を1.5倍にした 24px を基本のリズムとします。この値は他でも使うので、CSS Custom Properties で定義して、line-height-step プロパティを設定します。

基本のリズムを設定したら、本文の設定をします。

line-height-step を使う時には、margin をリズムの整数倍に揃える必要があります。個人的には日本語の段落間の空きはない方が好みなのですが、Webでは空ける場合も多いため、ここでは段落間を一行空きに設定しています。後で出てきますが、margin collapsingが使えない場合があるため、隣接セレクターを使っています。

また、line-height-step が行間を一定に揃えてくれるため、誤って余分な空白が入らないように line-height を小さめに設定しています。通常は問題ありませんが、複数のフォントが使われた時などには、CSSの仕組み上、行間が広がってしまう場合があるためです。

次に、画像や表は適用外とします。margin は見た目を確認しながら適当に設定してください。

最後に、見出しを「行取り」で揃えてみましょう。

ちょっとおまじないが出てきました。実は、line-height-step は行の高さを揃えるだけで、ブロックを揃えることができません。ブロックを揃えるための仕様も議論には上がっているのですが、行の議論でもう二年近く経っているので、ブロックの議論や実装は残念ながらまだ先です。このため、現段階でブロックを揃えるには、ブロックを inline-block にして行の中に収め、その行を揃える、という手法を取ります。width は、この inline-block を含む行を幅いっぱいにするためです。

これで <h2><h3> の高さは常に 24px の倍数になるように上下に余白が入ります。

モバイルなどの狭い画面では、見出しが複数行になる機会もあるので、このブロックの中では line-height-step をオフにし、小さめの line-height を設定します。見出しは、短めで、フォントも大きいので、通常は行間を詰めた方が見やすくなります。

最後に、見出しの上部の空きを、下部の空きより大きくするため、margin-top のみを一行分に設定します。これも好みですが、実際の空きは、「行取り」の調整のためにこれよりも大きくなるため、確認しつつ適切な値を探してみてください。上下の margin の合計値は 24px の倍数になるようにする必要があります。また、inline-block にしたため、隣接したブロックとの間でmargin collapsingが働きません。<p> で隣接セレクターを使ったのはこのためです。

これで完成です。試験運用機能を有効にしたChromeで確認できるはずです。サンプルはこちらにあります。確認が終わったら、試験運用機能は無効に戻しておいてください。

最後に

多くの方が、試されて最初に感じるのは「あんまり変わらないね」ということではないかと思います。ほぼすべての日本語ワープロにこの機能が入っていますが、気がついている人は多くはないのではないでしょうか。「行取り」「バーティカルリズム」のみならず、多くのタイポグラフィの改善は、一つ一つは非常に小さな変化ですが、積み重ねることで確実に読みやすくなります。ぜひ、お試しください。

Powered byNTT Communications

tag list

アクセシビリティ イベント エンタープライズ デザイン ハイブリッド パフォーマンス ブラウザ プログラミング マークアップ モバイル 海外 高速化 Angular2 AngularJS Chrome Cordova CSS de:code ECMAScript Edge Firefox Google Google I/O 2014 HTML5 Conference 2013 html5j IoT JavaScript Microsoft Mozilla Node.js PhoneGap Polymer React Safari SkyWay TypeScript UI UX W3C W3C仕様 Webアプリ Web Components WebGL WebRTC WebSocket