CSS でテキストをベースライン・グリッドに揃えるとなると、ベースラインの高さに応じて上下のパディングやマージンを調整するアプローチがよく見受けられますが、あまり実用的なものとは言いがたかったと思います。
p {
padding-top: 0.30116em;
padding-bottom: 0.19884em;
/* ... */
}
しかし、::before
と ::after
擬似要素を利用すると、かんたんにベースライン・グリッドに合わせることができます (Fig 1)。
/* Vertical rhythm unit: 0.5rem */
p {
line-height: 1.5rem;
margin: 0.5rem 0;
}
p::before,
p::after {
content: "";
display: inline-block;
height: 1.5rem; /* same as line-height */
}
p::before {
vertical-align: 0;
}
p::after {
vertical-align: -1rem; /* margin-bottom - line-height */
}
まず最初に、ページを通じて基準になる高さの「単位」を決めます。ここでいう単位は CSS の length の unit ではなく、ページの「縦のリズム」を構成する最小単位のことです。0.5 rem などがわかりやすくて良いと思います。
ボックスの line-height
と上下のマージン、パディングは、つねにこの単位の整数倍で指定します。この時点でボックス自体はベースライン・グリッド上に乗りますが、ベースラインの位置は通常のフローのまま (Fig 2)。
最初の行の先頭にある ::before
擬似要素が inline-block
としてベースライン上に配置されていて、かつ line-height
と等しい高さを持つので、行ボックスが上方向に押し広げられるかたちで、最初の行のベースラインがグリッドに合います。
2 行目以降も、line-height
が「単位」の整数倍であるため、ベースラインはつねにグリッド上に来ることになります。
そして最後の行の末尾にある ::after
の vertical-align
に「単位」の負の整数倍を指定して行ボックスを下方向に押し広げるのに加え、下マージンまたはパディングもやはり「単位」の整数倍とすることで、後続するボックスの上辺をグリッドに揃えることができます。
なお、::before
と ::after
には幅を指定する必要がなく、横方向のレイアウトには影響を与えません。ただし、リスト項目をインライン化したリスト要素 (ol
、ul
、dl
) などでマークアップに改行があると、行頭にスペースが生じる場合があります。これはリスト項目のマークアップの改行を除去したり閉じタグを省略したりすれば回避できます。
もしテーブル要素などでボーダーがあってリズムがずれる場合は、擬似要素の vertical-align
をボーダー幅の分だけ調整します (ただし、テーブル要素はボーダーのスタイリングにブラウザーごとの細かな違いがけっこうあり、完璧に揃えるのは難しいかも)。
th,
td {
border-bottom: 1px solid silver;
line-height: 1rem;
/* ... */
}
th::before, th::after,
td::before, td::after {
content: "";
display: inline-block;
height: 1rem;
}
th:before,
td:before {
vertical-align: -1px;
}
th::after,
td::after {
vertical-align: -0.5rem;
}
かんたんなデモ も用意しました。G キーでガイドラインをトグルできます。
この擬似要素を使ったアプローチの難点として、::before
と ::after
の両方をつねに必要としてしまうところが挙げられます。もしこれらをほかのスタイルに利用している場合はマークアップを追加するしかないです。
また、画像までベースライン・グリッドに揃えるのはおそらく CSS だけでは無理で、vertical-align
を middle
などにしたうえで、JavaScript で高さを単位の整数倍に調整するなどのアプローチが必要だと思います。
こういったレイアウトは、やりはじめるとパラノイアックに追求したくなりがちですが、やはりやりすぎはよくないです。すべての要素を完全にベースライン・グリッドに合わせるのは、かなりシンプルなページでも難しいし、もしそれができたとしても、その結果として読みやすいものになるかどうかはまた別なので。