CSS の em と rem の違い
CSS でモバイルやタブレット端末にも対応したレスポンシブデザインするとき重要な役割を持つけれども, どちらを使えばいいのか混乱しがちな 2 つのユニット em と rem の違いをできるだけ簡単に説明します.
em
の場合
まず em は font-size
の値として指定されるか, 他の値として指定されるかで意味合い変わってきます.
font-size
の値として使われる場合
もし font-size
の値として指定されると, その font-size
が定義されている要素の親要素の font-size
から相対的なフォントサイズになります.
もしどれだけ上層の親要素にも font-size
が定義されていない場合 (html
要素にも), ブラウザデフォルトの 16px
が暗黙的に html
要素の font-size
として定義されます.
つまりは html
要素の子要素で定義された font-size: 1em;
は 16 * 1
で 16px
となります.
もし font-size: 1.2em;
なら 16 * 1.2
で 19.2px
となります.
See the Pen MBzREw by 濱田悠 (@yu8mada) on CodePen.
もし font-size: 0.8em;
が定義された要素が入れ子になった場合, 入れ子の子要素の font-size
は, html
要素の font-size: 16px;
と入れ子の親要素の font-size: 0.8em
と入れ子の子要素の font-size: 0.8em
で 16 * 0.8 * 0.8
となり 10.24px
となります.
See the Pen RBqmrd by 濱田悠 (@yu8mada) on CodePen.
このように em
で指定される font-size
というのは親要素の font-size
の影響を段階的に受ける相対的なフォントサイズになります.
font-size
が定義された要素を入れ子にしたら入れ子にした分だけ, 相対値が適用されていきます.
font-size
以外の値として使われる場合
今度は em
が font-size
以外の値として使われた場合を見てみます.
例えば padding
の値として使われる場合を想定してみます.
em
が padding
の値として使われると, font-size
の時と同じように, 親要素の font-size
の相対的なパディングサイズになります.
なので padding: 1em;
が定義された子要素のパディングサイズは html
要素のデフォルトの font-size
が 16px
なので, 16 * 1
で 16px
になります.
See the Pen 2018/08/09/the-difference-between-em-and-rem-in-css #3 by 濱田悠 (@yu8mada) on CodePen.
親要素の font-size
が 0.8em
で子要素の padding
が 0.8em
の入れ子の場合, その子要素のパディングサイズは, 親要素と html
要素の font-size
の影響を受けるので, 16 * 0.8 * 0.8
で 10.24px
となります.
See the Pen 2018/08/09/the-difference-between-em-and-rem-in-css #4 by 濱田悠 (@yu8mada) on CodePen.
ただ注意すべきことがあります.
それは子要素でも font-size
が定義された場合です.
例えば font-size: 0.8em;
と入れ子の子要素でも定義された場合, その子要素のバディングサイズは, その子要素に定義された font-size
との相対的なパディングサイズなります.
その子要素の font-size
は親要素と html
要素の font-size
の相対値なので, つまりは 16 * 0.8 * 0.8 * 0.8
で子要素のバディングサイズは 8.192px
となるわけです.
See the Pen 2018/08/09/the-difference-between-em-and-rem-in-css #5 by 濱田悠 (@yu8mada) on CodePen.
少し直感に反するので注意が必要です.
rem
の場合
今度は rem
の場合です.
rem
は em
同様, font-size
から相対的なサイズを得るためのユニットですが, どの要素の font-size
から相対的なサイズを計算するかというのが決定的な違いになります.
rem
は常に html
要素の font-size
からの相対値になります.
なので親要素が html
要素でない限り, 親要素にどれだけ font-size
が定義されていようと, その親要素の font-size
の影響は受けません.
常に html
要素の font-size
からの相対値となります.
なので rem
の r
は Root (html
要素) の r
なのです.
font-size
の値として使われる場合
なので次のように子要素に font-size: 0.8rem;
と定義した場合, その子要素の親要素の font-size
が 1.2em
で 16 * 1.2
で 19.2px
であっても, 19.2 * 0.8
で 15.36px
とはならず, html
要素の font-size
からの相対値となるので 16 * 0.8
で 12.8px
となるわけです.
See the Pen 2018/08/09/the-difference-between-em-and-rem-in-css #6 by 濱田悠 (@yu8mada) on CodePen.
font-size
以外の値として使われる場合
このように rem
は常に html
要素の font-size
からの相対値となるので, 例えば padding: 0.8rem;
が定義されている子要素に font-size: 1.2em;
が定義されていようと em
の場合と異なり, 同要素内の font-size
の影響は全く受けません.
つまりは 16 * 1.2 * 0.8
で 15.36px
とならず, 16 * 0.8
で 12.8px
となります.
See the Pen 2018/08/09/the-difference-between-em-and-rem-in-css #7 by 濱田悠 (@yu8mada) on CodePen.
まとめ
まとめますと次のようになります:
em
がfont-size
の値として使われると, 親要素のfont-size
との相対値になります.em
がfont-size
以外の値として使われると, 同要素内のfont-size
との相対値になります.rem
がfont-size
の値として使われると,html
要素のfont-size
との相対値になります.rem
がfont-size
以外の値として使われても, 同様にhtml
要素のfont-size
との相対値になります.
このことから em
は, 親要素の font-size
や, 同要素内の font-size
に応じてパディングなどのサイズを変化させたい場合に使われ, rem
は親要素や同要素内のfont-size
がどんな値に定義されていても常に一貫したサイズを提供したいような場合に使われます.
ちなみに html
要素に font-size
を定義する場合, デフォルトで 16px
ですが, だからと言って次のように font-size: 16px;
のような固定値を設定してしまうのはよくないと言われています:
/* Bad practice */
html {
font-size: 16px;
}
というのもユーザがブラウザのフォントサイズをお好みの値に変更したとしても, その変更が反映されず, その例の場合, 常に 16px
に固定されてしまうからというものです.
なので html
要素に font-size
を定義したい場合は, 固定値の px
ではなく, %
, em
, rem
といった相対値のユニットを使うことが望ましいとされています:
html {
/* This calculates to 10px (16 * 0.625) */
font-size: 62.5%;
}
ちなみに当ブログの html
要素の font-size
は @media
を使って, デバイス毎の viewpoint に応じて font-size
を 10px
から 14px
まで変更するようにしています:
html {
/* 10px */
font-size: 62.5%;
}
@media (min-width: 576px) {
html {
/* 11px */
font-size: 68.75%;
}
}
@media (min-width: 768px) {
html {
/* 12px */
font-size: 75%;
}
}
@media (min-width: 992px) {
html {
/* 13px */
font-size: 81.25%;
}
}
@media (min-width: 1200px) {
html {
/* 14px */
font-size: 87.5%;
}
}
%
による指定なので, ユーザが指定するブラウザのフォントサイズに応じてスケールします.
あと Bootstrap 4 を使っているので, それぞれ xs
, sm
, md
, lg
, xl
という 5 つのサイズに対応させています.
ただ僕は CSS, Web デザインに関してはあまり自信がないので, 参考程度にしていただけたらと思います.
と少し脇道に逸れてしまいましたが, em
と rem
ってそんな違いがあるんです.
僕はどういう時に em
を使うべきなのか, rem
を使うべきなのかは, 正直未熟な部分もありはっきりした答えを出すことができないのですが, em
を使う派と rem
を使う派という二派が存在しているそうなので, 明確にこっちを使うべきと判断するのは難しいのかもしれないです.
なので僕は em
と rem
のそれぞれの特徴をおさえて, 状況に応じて使い分けていきたいなと思ってます.
関連記事
Ruby の正規表現を備忘録としてまとめてみた2018.08.30
Git のコミット履歴を大胆に書き換えるなら git rebase -i がオススメ2018.08.23
Ruby の関数プログラミングでオイラー積を計算してみた2018.07.02
Git のマージコンフリクトを解決する方法2018.06.13
Git で変更されたファイルを部分的にステージする方法2018.11.01