CSS におけるサイズ単位のひとつである rem
。これは主に文字を対象とするものだが、これを他の要素へ適用することについて考察する。
CSS のサイズ単位は絶対長と相対長へ大別される。詳細は以下の記事を参照のこと。
絶対長は他の長さに影響されず、サイズは常に一定。代表的なものは px
や pt
など。ディスプレイ (以降、本記事ではこの語を PC 向けディスプレイとして用いる) や紙面などの出力媒体で定められた長さとなる。CSS は主に Web ブラウザーを対象とするため px
を利用することが多い。本書のように紙面も想定しているならば @media print
で pt
や cm
へ切り替えることもある。
相対長はなんらかの長さに対してサイズが変化する。この性質により出力媒体によるサイズの差へ対応しやすい。代表的なものは em
、そして本記事の主題である rem
など。%
は単位ではなく割合だが、用途としては相対なので本記事ではこちらに含める。
先に絶対長と相対長それぞれの課題を挙げ、それらを解決する手段としての rem
を考察する。
絶対長はそれ自体の長さこと絶対的だが、出力媒体には依存する。媒体が紙面であれば物理サイズとしての出力は固定なのでよい。しかしディスプレイを対象とする場合、解像度とピクセル密度による可変性が課題となる。
かつてディスプレイのピクセルは固定的であった。しかし 2010 年に iPhone 4 が採用した Retina ディスプレイのあたりから、表示上の長さは変えず、ピクセル密度を高めて精細化する方式が普及し始める。そして現在 (2022 年) は様々なプラットフォームで高解像度・高精細化が一般化して、ピクセル固定を前提とする px
への影響が目立つようになった
px
を指定しても OS や Web ブラウザーがディスプレイ解像度とピクセル密度を加味して、よしなに長さを変更してくれる。しかしこの処理にも限界があって、例えば 4K ディスプレイ (3840 × 2160) 上で font-size: 12px
の文字を表示する際、解像度そのままだとディスプレイの物理サイズによっては読めたものではない。物理サイズが 27 インチぐらいあればよいのだが、15 インチなどでは文字が点のように見えるだろう。そのため OS のディスプレイ設定で拡大指定する必要がある。
では 14px
、16px
のように大きくしてゆけばよいのだろうか?そうした場合、逆に低解像度の環境としては大きすぎるかもしれない。ここに課題の本質がある。それは絶対長を想定しても実際には可変、つまり相対長のように振る舞うことである。絶対長を保証するには出力媒体を固定しなければならない。
相対長は基準に応じて長さを変える柔軟性があるため、出力媒体の差を緩和した表示を可能とする。ただし基準が課題となる。
em
や %
は親に指定された長さを基準とするため、サイズ予想が難しい。例えば以下の HTML/CSS において <p>
の font-size
は親の .parent
に指定された 12px
を基準とした 0.9em
となる。そのため 10.8px
として出力されるが、これは想定どおりだろうか?
<style>
.parent {
font-size: 12px;
}
p {
font-size: 0.9em;
}
</style>
<div class="parent">
<p>テキスト</p>
</div>
親のサイズ指定が絶対長ならば、まだよい。これが相対長になるとますます予想は難しくなる。例えば以下の HTML/CSS で <p>
のサイズを予想できるだろうか?正解は 9.72px
だが、<p>
の位置を .parent
直下へ移動すると前述の 10.8px
になる。
<style>
.parent {
font-size: 12px;
}
.child {
font-size: 0.9em;
}
p {
font-size: 0.9em;
}
</style>
<div class="parent">
<div class="child">
<p>テキスト</p>
</div>
</div>
この難しさもあってか、em
よりも px
を選ばれることがある。もしくは em
を採用しつつも HTML/CSS を慎重に設計する、BEM のような CSS 命名で親子関係の明確化とある程度の一意性を担保する、などの方法により想定内へ収めたりする。
しかし親の長さを基準とする以上、本質的な課題は解決していない。
相対長のひとつに rem
がある。
これは長さの基準を親ではなくページのルート要素に設定された文字サイズとする点が特徴。HTML のルート要素は <html>
なので、ここが font-size: 16px
ならば 1rem
は 16px
になる。<html>
の既定文字サイズは Web ブラウザーの設定となるため、rem
にも反映される。
つまり相対長でありながら基準をひとつとすることで、絶対長のように扱える。試しに相対長の課題として挙げた HTML/CSS へ rem
を適用してみよう。これを Web ブラウザーで表示すると、<p>
の文字は 14.4px
になった。1rem
に変えたら 16px
となるので、このサイズに対する 0.9
ということなのだろう。
<style>
.parent {
font-size: 12px;
}
.child {
font-size: 0.9em;
}
p {
/* 0.9em を 0.9rem に変更 */
font-size: 0.9rem;
}
</style>
<div class="parent">
<div class="child">
<p>テキスト</p>
</div>
</div>
ここでひとつ注意が必要。ルート要素 <html>
の文字サイズがどこのように決定されるか?である。これは Web ブラウザーによって挙動が異なるようだ。MacBook Pro 15 2019 (Monterey) 上で試したところ、以下のようになった。
<html>
の既定は 16px
<html>
要素へ明示的に font-size: 1rem
を指定すると Firefox に設定された文字サイズが反映される<html>
要素の指定がなくとも Chrome に設定されたサイズ (この環境だと大 = 20px) が反映される<html>
の既定は 16px
font-size
は無視されて最小サイズ設定が反映される16px
を基準とした rem
が最小サイズを上回れば、それが反映される24px
で 1rem
だと既定の 16px
なので 24px
になるが、2rem
なら 32px
なのでそのまま反映されるユーザーが明示的に文字サイズを指定した場合を考慮すると、<html>
に対して明示的に 1rem
を指定するのがよさそうだ。そうすれば em
や %
と異なり、親要素になにが設定されていても妥当なサイズを設定してくれるだろう。
基本的に rem
は文字サイズに対する相対長の単位として使用される。ならば文字と文章が主体となりがちな Web ページは、px
や %
よりも rem
でレイアウトするほうが管理しやすいのではなかろうか?
例えばヘッダー、フッター、1 カラム中央寄せの本文で構成されたブログがあるとする。HTML として以下を想定。
<header>
<h1>ブログ</h1>
<nav>メニュー</nav>
</header>
<article>
<h1>記事 1</h1>
<p>本文</p>
</article>
<footer>連絡先</footer>
<article>
の横書き本文を中央寄せにしたい。全体レイアウトは中央寄せとレスポンシブともに適用済みで、ページ幅が十分に広い場合の max-width
を想定している。その際、<article>
の幅へ指定するサイズはどうしたらよいだろうか?サイズ指定の候補としては絶対長から px
、相対長は %
と rem
を選んだ。
px
1024px
などの固定値を指定%
90%
や 80%
などを指定rem
40rem
など 1 行に表示したいおおよその文字数を指定本文幅の指定として px
は現代でも多数ではなかろうか。しかし狭まる分にはレスポンシブレイアウトするとしても、広くなる場合は想定されていないのではなかろうか?高解像度ディスプレイで Web ブラウザーを広げたとき、幅 1024px
ですら狭く感じられることがある。
%
はあまり見かけない。しかし稀に 90%
や 80%
を指定しているサイトがあり、ページ幅が広いと行長が 100 文字を超えて文章を読むに厳しいことがある。
rem
はどうか。手前味噌だが私のサイト akabeko.me では max-width: 45rem
を指定している。他に rem
幅の例を見たことはないが、少なくとも私のサイトは高解像度ディスプレイの広いページ幅でみても、行長としては最大 45rem
なので広くも狭くも感じない。
メンテナンス性についても %
は論外として、px
のように解像度を気にしなくて済むため、意外によい方法ではなかろうか?
margin
や padding
の指定についても rem
を推したい。
これらは font-size
のサイズ単位とあわせることでレイアウト予想を立てやすくなる。font-size
が px
なら px
、rem
なら rem
へ統一するのが好ましい。
画像のサイズ指定は種類による。図や写真などのラスター画像はピクセル数とアスペクト比、本文などのコンテンツ幅を加味して px
や %
を指定するのがよいだろう。ラスター画像のサイズはピクセル単位となるため、整数倍 px
以外を指定すると綺麗に描画されない可能性もある。
UI 画像 (ボタンのアイコンなど) は文字と併置される機会も多いため、rem
が好ましい。かつて rem
がない時代は UI 画像と文字サイズを px
統一してレイアウトすることが多かった。ラスター画像の描画的にも px
指定は理にかなっている。現在も font-size
に px
を採用する向きがあるのは、この慣習が一因かもしれない。
しかし現代は rem
があり、UI 画像も SVG やアイコンフォントのようなベクター画像を選べる。ベクター画像はサイズを変更しても滑らかに描画されるため、rem
指定を採用するよい機会といえる。
CSS のサイズ単位を rem
寄せにした場合の考察をまとめてみた。「ページの本文幅」で触れているように、私のサイトで導入してみたところ意外によく、React などの View 系ライブラリーで UI コンポーネントを実装する際もレイアウト予想を立てやすいので導入を検討している。
本記事は Vivliostyle の本なので、おわりに本記事の主題と関係する Vivliostyle の新機能を紹介する。
Vivliostyle は v2.17.0 で CSS 変数へ対応した。
この機能を利用することでサイズ単位を抽象化できるかもしれない。Web と印刷を @media
で分岐するように、サイズ指定をすべて CSS 変数化して出力媒体にあったものへ切り替えるのはどうか。
レイアウト検証としても役立ちそうだ。
例えばサイズ単位が px
中心のページがあるとする。これを rem
へ移行させる場合、まずはサイズ指定を役割や値の内容で命名した CSS 変数へ括りだす。それらをレイアウト検証しながら少しずつ rem
へ置き換えてゆくのはどうか。検証で問題が起きたら CSS 変数の値を px
へ戻せばよい。
このように可能性のある機能で、本書のように Vivliostyle を利用したコンテンツの作成が大きく改善しそうな予感がある。