- CSS
CSS単位の使い分け|remとemの違い・vw・vh・px早見表
CSS の単位とは、長さや大きさを「何を基準に測るか」を決めるもので、px は画面上の固定の長さ、rem はルート(html 要素)の文字サイズ、em はその要素の文字サイズ、vw・vh は画面(ビューポート)の幅と高さを基準にします。 迷ったときの目安は、文字サイズと余白は rem、部品の内側で文字に比例させたい所は em、線の太さは px、画面いっぱいの高さは dvh か svh です。
この記事では、主要な17種類の単位を1枚の表にまとめたうえで、「em を入れ子にすると文字がどんどん大きくなる」「% は何に対する割合なのか」「ブラウザの文字サイズ設定を変えると px と rem でどう差が出るか」を、Chromium 141 で取得した計算値(getComputedStyle の値) で確かめます。スマートフォンで 100vh がはみ出す理由と dvh・svh・lvh の使い分け、html { font-size: 62.5% } の考え方、用途別の選び方の表も載せています。
CSS 単位の早見表
まずはこの表だけで、ほとんどの場面の単位を選べます。 「1単位の実測値」は、画面 1000×800px、対象の要素が font-size: 20px; line-height: 1.6; font-family: monospace、ルートの文字サイズが 16px のときの値です(Chromium 141 で取得)。
| 単位 | 基準 | 1単位の実測値 | 主な用途 | 注意点 |
|---|---|---|---|---|
px |
画面上の固定の長さ(CSS ピクセル) | 1px | 線の太さ、影、細かな位置合わせ | ブラウザの文字サイズ設定に連動しない |
em |
その要素の font-size(font-size に書いたときは親の文字サイズ) | 20px | ボタンの内側の余白、アイコンの大きさ | 入れ子で掛け算になる |
rem |
ルート(html)の font-size | 16px | 文字サイズ、余白、最大幅 | html の font-size を変えると全体が変わる |
% |
プロパティごとに違う(後述の表) | ― | 幅、流動的なレイアウト | 何に対する割合かをプロパティごとに確認 |
vw |
ビューポートの幅の 1% | 10px | 画面幅に連動する大きさ | 文字サイズに単独で使うと拡大が効きにくい |
vh |
ビューポートの高さの 1% | 8px | 画面の高さに連動する大きさ | スマートフォンではツールバーの分だけ大きくなる |
vmin |
幅と高さの小さいほうの 1% | 8px | 縦横どちら向きでも収めたい正方形など | ― |
vmax |
幅と高さの大きいほうの 1% | 10px | 画面を覆う背景の装飾 | ― |
dvh |
今のツールバーの状態に合わせた高さの 1% | 8px | 画面にぴったり合わせたい全画面表示 | スクロール中に値が変わる |
svh |
ツールバーが出ているときの高さの 1% | 8px | ファーストビュー、はみ出させたくない高さ | ツールバーが隠れると下に余白ができる |
lvh |
ツールバーが隠れたときの高さの 1% | 8px | 背景など、多少隠れてもよいもの | ツールバーが出ていると下が隠れる |
ch |
そのフォントの「0」の幅 | 12.0312px | 1行の文字数の目安(欧文)、入力欄の幅 | 日本語は 1ch より広い。全角は ic が近い |
ex |
そのフォントの小文字 x の高さ | 11px | 小さな位置調整 | フォントによって変わる |
lh |
その要素の line-height の計算値 | 32px | 「3行ぶんの高さ」などの指定 | 比較的新しい単位 |
cqw |
コンテナ(container-type を付けた祖先)の幅の 1% | ― | 部品の幅に連動する文字サイズ・余白 | コンテナがないと小さいビューポート基準になる |
cqi |
コンテナのインライン方向(横書きなら幅)の 1% | ― | 同上(縦書きにも対応) | 同上 |
fr |
グリッドの残りの空きを分け合う比率 | ― | grid-template-columns など | グリッド専用。長さの単位ではない |
デスクトップのブラウザには伸び縮みするツールバーがないので、vh・dvh・svh・lvh はすべて同じ 8px になっています。差が出るのはスマートフォンです(後述)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS単位の使い分け|remとemの違い・vw・vh・px早見表」
単位の全体像:絶対単位と相対単位
CSS の長さの単位は、大きく2種類に分かれます。
| 種類 | 意味 | 単位 |
|---|---|---|
| 絶対単位 | 何にも連動しない固定の長さ | px、pt、in、cm、mm、pc、Q |
| 相対単位(文字基準) | 文字サイズやフォントの寸法に連動 | em、rem、ch、ex、lh、rlh、ic、cap |
| 相対単位(画面基準) | ビューポートの大きさに連動 | vw、vh、vmin、vmax、dvh、svh、lvh、vi、vb |
| 相対単位(コンテナ基準) | 祖先のコンテナの大きさに連動 | cqw、cqh、cqi、cqb、cqmin、cqmax |
| 割合 | 親や自分の値に対する割合 | % |
| グリッド専用 | 空きスペースの比率 | fr |
早見表に入れなかった単位も、同じ条件で実測しておきます。
1in -> 96px 1cm -> 37.7812px 1mm -> 3.76562px
1pt -> 1.32812px 1pc -> 16px 1Q -> 0.9375px
1rlh -> 18px 1ic -> 20px 1cap -> 14px
1vi -> 10px 1vb -> 8px 1dvw -> 10px
1in は 96px、1pt は 1/72 インチ(約 1.333px)と決まっています。上の値がわずかに小さいのは、ブラウザがレイアウトの長さを 1/64px 刻みに丸めるためです。pt・cm・mm などは印刷用のスタイル(@media print)向けで、画面用のスタイルでは px と相対単位を使います。
ic は「水」という漢字の幅を基準にする単位で、全角1文字ぶんの幅に当たります。上の結果でも、20px の文字に対して 1ic は 20px でした。日本語で「1行を40文字に収めたい」ときは max-width: 40ic と書けます。対応状況の実測は Chromium 141 だけなので、広く使うときは max-width: 40em を併記しておくと安心です。
rem と em の違い:入れ子で実測する
em は「掛け算」、rem は「常にルート基準」
rem と em はどちらも文字サイズを基準にしますが、基準にする要素が違います。
| 単位 | 基準 | 入れ子にしたとき |
|---|---|---|
em |
その要素の font-size。font-size プロパティに書いた場合は親要素の文字サイズ | 親の結果にさらに掛け算される |
rem |
ルート(html 要素)の font-size | どこに書いても同じ値 |
入れ子のリストで比べます。li の文字サイズを 1.2 倍にする指定を、em と rem でそれぞれ書きます。
<ul class="em"><li>1階層<ul><li>2階層<ul><li>3階層<ul><li>4階層</li></ul></li></ul></li></ul></li></ul>
<ul class="rem"><li>1階層<ul><li>2階層<ul><li>3階層<ul><li>4階層</li></ul></li></ul></li></ul></li></ul>
.em li { font-size: 1.2em; }
.rem li { font-size: 1.2rem; }
Chromium 141 で各階層の font-size の計算値を取得した結果です(ルートの文字サイズは 16px)。
| 階層 | 1.2em の計算値 | 1.2rem の計算値 |
|---|---|---|
| 1階層 | 19.2px | 19.2px |
| 2階層 | 23.04px | 19.2px |
| 3階層 | 27.648px | 19.2px |
| 4階層 | 33.1776px | 19.2px |
em のほうは 16 × 1.2 × 1.2 × 1.2 × 1.2 = 33.1776px と、階層が深くなるたびに 1.2 倍が重なっています。rem のほうは、どの階層でも 16 × 1.2 = 19.2px のままです。文字サイズの指定に rem が選ばれるのは、この「どこに書いても同じ値になる」性質のためです。
em が役立つ場面:部品の中を文字に比例させる
em の「その要素の文字サイズに連動する」性質は、部品の内側ではむしろ便利です。ボタンの余白を em で書くと、文字サイズを変えるだけでボタン全体が同じ比率で大きくなります。
.btn {
font-size: 24px;
padding: 0.5em 1em; /* 上下 12px・左右 24px */
border-radius: 0.25em; /* 6px */
}
.btn-rem {
font-size: 24px;
padding: 0.5rem 1rem; /* 上下 8px・左右 16px(文字サイズと無関係) */
}
実測値:
.btn paddingTop=12px paddingLeft=24px borderTopLeftRadius=6px
.btn-rem paddingTop=8px paddingLeft=16px
.btn は文字サイズ 24px を基準に余白が決まり、.btn-rem はルートの 16px を基準に決まっています。大・中・小のサイズ違いのボタンを作るとき、em で書いておけば font-size を1か所変えるだけで済みます。
| 場面 | 向いている単位 | 理由 |
|---|---|---|
| 文字サイズ(font-size) | rem | 入れ子の影響を受けない |
| ページ全体の余白・セクション間隔 | rem | サイト全体で同じ基準にそろう |
| ボタン・バッジ・アイコンなど部品の内側 | em | 文字サイズに比例して全体が拡大・縮小する |
| 文字の横に置くアイコンの大きさ | em(width: 1em; height: 1em) |
隣の文字と同じ大きさになる |
| letter-spacing、text-indent | em | 文字の大きさに比例させるのが自然 |
| line-height | 単位なしの数値(1.5 など) | 子要素にも「倍率」として引き継がれる |
line-height だけは特別で、単位を付けない数値で書くのがおすすめです。line-height: 1.5 は「各要素の文字サイズの 1.5 倍」として子に引き継がれますが、line-height: 1.5em や 150% は計算済みの長さ(px)が引き継がれるため、子の文字サイズが大きいと行が重なります。
% が何を基準にするかの表
% は便利な単位ですが、プロパティによって「何の何%か」が変わります。 ここを押さえると、レイアウトの計算がぐっと読みやすくなります。
| プロパティ | % の基準 |
|---|---|
width、max-width、min-width |
親(包含ブロック)の幅 |
height、max-height、min-height |
親の高さ(親の高さが決まっているときだけ効く) |
padding(上下左右すべて) |
親の幅 |
margin(上下左右すべて) |
親の幅 |
font-size |
親の文字サイズ |
line-height |
その要素自身の文字サイズ |
top、bottom |
位置の基準になる祖先(包含ブロック)の高さ |
left、right |
位置の基準になる祖先の幅 |
transform: translate() |
その要素自身の幅・高さ |
border-radius |
その要素自身の幅・高さ |
background-position |
「要素の大きさ − 画像の大きさ」に対する割合 |
上から6行を実測します。親を幅 400px・高さ 200px・文字サイズ 20px にして、子にすべて % で指定します。
.box { width: 400px; height: 200px; font-size: 20px; }
.child {
width: 50%; height: 50%;
padding: 10%; margin-top: 10%;
font-size: 150%; line-height: 150%;
}
width=200px height=100px paddingTop=40px paddingLeft=40px marginTop=40px fontSize=30px lineHeight=45px
| 指定 | 計算値 | 計算の内訳 |
|---|---|---|
width: 50% |
200px | 親の幅 400 × 0.5 |
height: 50% |
100px | 親の高さ 200 × 0.5 |
padding: 10%(上) |
40px | 親の幅 400 × 0.1(高さの 200 ではない) |
margin-top: 10% |
40px | 親の幅 400 × 0.1 |
font-size: 150% |
30px | 親の文字サイズ 20 × 1.5 |
line-height: 150% |
45px | 自分の文字サイズ 30 × 1.5 |
上下の padding と margin も、親の「幅」が基準になる点が意外に感じられる所です。この性質は、以前は「padding-top: 56.25% で 16:9 の箱を作る」という書き方に使われていました。今は aspect-ratio: 16 / 9 で同じことが1行で書けます。
height: 50% が効かないときは、親の高さが決まっていない(auto のまま)ことがほとんどです。親に height を指定するか、Flexbox や Grid で高さを決めると解決します。
ブラウザの文字サイズ設定を変えたときの px と rem
ブラウザには「文字サイズ」の設定があります(Chrome なら「設定 → デザイン → フォントサイズ」)。見やすさのために既定の 16px を 20px や 24px に変えている利用者もいます。この設定に連動するのが rem・em・% で、連動しないのが px です。
Chromium 141 で、既定の文字サイズを 16px・20px・24px に切り替えて計算値を取得しました。
.px { font-size: 16px; }
.rem { font-size: 1rem; }
| ブラウザの既定の文字サイズ | html の計算値 | 16px の文字 |
1rem の文字 |
|---|---|---|---|
| 16px(既定) | 16px | 16px | 16px |
| 20px | 20px | 16px | 20px |
| 24px | 24px | 16px | 24px |
px で書いた文字は、設定を変えても 16px のままです。rem で書いた文字は設定に合わせて大きくなります。文字サイズを rem で書くと、利用者が選んだ文字の大きさがそのまま反映されます。
余白や幅も同じです。既定の文字サイズを 24px にしたときの結果です。
| 指定 | 既定 16px のとき | 既定 24px のとき |
|---|---|---|
width: 20em(文字 1rem) |
320px | 480px |
width: 320px |
320px | 320px |
padding: 1.5rem |
24px | 36px |
padding: 24px |
24px | 24px |
font-size: clamp(1.5rem, 1rem + 2vw, 3rem) |
36px | 44px |
font-size: 4vw |
40px | 40px |
文字だけ大きくなって余白や箱の幅がそのままだと、窮屈に見えたり文字があふれたりします。文字に合わせて広がってほしい余白・幅は rem や em で、文字と無関係に固定したい線などは px で書き分けると、文字サイズを変えた利用者にも整った見た目になります。
最後の行のとおり、4vw のように vw だけで書いた文字サイズは、文字サイズ設定を変えても大きくなりません。clamp() の中で rem と組み合わせると、設定が反映されます。計算式の作り方は「CSS clamp()の使い方」の記事で詳しく扱っています。
なお、ブラウザの「ズーム」(Ctrl と + キー)は別の仕組みで、px も含めてページ全体が拡大されます。ここで扱ったのは、ズームではなく「文字サイズだけ」を変える設定の話です。
vw・vh とスマートフォンの 100vh 問題
vw と vh の基本
vw はビューポートの幅の 1%、vh は高さの 1% です。1000×800px の画面なら 1vw は 10px、1vh は 8px になります(早見表の実測値)。
.hero { min-height: 100vh; } /* 画面の高さいっぱい */
.banner { width: 100vw; } /* 画面の幅いっぱい */
.square { width: 50vmin; height: 50vmin; } /* 縦向きでも横向きでも収まる正方形 */
width: 100vw には、知っておくと役立つ点があります。100vw は縦スクロールバーの幅を含むため、スクロールバーが常に表示される環境では、ページの幅よりスクロールバーの分だけ広くなり、横スクロールが出ることがあります。画面の幅いっぱいにしたいだけなら width: 100% のほうが意図どおりになります。
スマートフォンで 100vh がはみ出す理由
スマートフォンのブラウザでは、スクロールするとアドレスバーなどのツールバーが引っ込み、表示領域が広がります。このとき vh は「ツールバーが隠れたときの大きい高さ」を基準にしています。 そのため、ページを開いた直後(ツールバーが出ている状態)に height: 100vh の要素を置くと、ツールバーの分だけ画面からはみ出し、下端のボタンなどが隠れます。
MDN の length の解説でも、接頭辞のない vh・vw は「大きいビューポート」の単位(lvh・lvw)と同じ、と説明されています(今回確認)。
そこで用意されたのが、3種類のビューポート単位です。
| 単位 | 基準 | ツールバー表示中 | ツールバーが隠れたあと | 値の変化 |
|---|---|---|---|---|
svh(small) |
ツールバーが出ているときの高さ | ぴったり | 下に余白ができる | 変わらない |
lvh(large) |
ツールバーが隠れたときの高さ | 下がはみ出す | ぴったり | 変わらない |
dvh(dynamic) |
今の状態の高さ | ぴったり | ぴったり | スクロール中に変わる |
vh |
lvh と同じ | 下がはみ出す | ぴったり | 変わらない |
同じ考え方で、幅には svw・lvw・dvw、小さいほう・大きいほうには svmin・dvmax なども用意されています。
対応状況
web.dev の記事(2022年11月公開)で、次のバージョンから使えることを確認しました。
| ブラウザ | svh・lvh・dvh が使えるバージョン |
|---|---|
| Chrome / Edge | 108 以降 |
| Firefox | 101 以降 |
| Safari | 15.4 以降 |
3つのブラウザエンジンすべてで使える状態になってから数年が経っており、現在は安心して使える単位です。検証環境の Chromium 141 でも CSS.supports("height:100dvh") と CSS.supports("height:100svh") はどちらも true でした。
コピペ用:全画面セクションの書き方
/* 画面の高さいっぱいのセクション */
.hero {
min-height: 100vh; /* dvh に対応していないブラウザ向け */
min-height: 100svh; /* ツールバーが出ていてもはみ出さない */
}
/* 画面に固定するモーダルやチャット画面(常に画面ぴったりにしたい) */
.fullscreen-app {
height: 100vh;
height: 100dvh;
}
同じプロパティを2行書くと、対応しているブラウザでは後の行が使われ、対応していないブラウザでは後の行が読み飛ばされて前の行が使われます。
| 場面 | おすすめ | 理由 |
|---|---|---|
| ファーストビューのセクション | min-height: 100svh |
スクロールしても高さが変わらず、がたつかない |
| 画面全体を使うアプリ風の画面、モーダル | height: 100dvh |
常に見えている範囲にぴったり合う |
| 画面を覆う背景・装飾 | 100lvh |
ツールバーが隠れたときにも隙間ができない |
height ではなく min-height |
中身が多いとき | 中身が画面より長くても切れない |
dvh はスクロール中に値が変わるため、大きな要素の高さに使うと、ツールバーが動くたびにレイアウトが計算し直されます。ファーストビューのように「最初の見た目が合っていればよい」場面では svh のほうが落ち着いた動きになります。
なお、検証環境でスマートフォン(iPhone 13)の画面サイズを再現して測ると、100vh・100dvh・100svh・100lvh はすべて 664px で同じ値でした。画面サイズの再現ではツールバーの伸び縮みまでは再現されないためです。3つの単位の差は、実機のブラウザで確かめる必要があります(今回は未実行)。
そのほかの便利な単位:ch・lh・コンテナクエリ単位・fr
ch:入力欄や欧文の行の長さに
ch は、そのフォントの数字「0」の幅です。等幅フォント 20px での実測値は 12.0312px でした。
input.zip { width: 8ch; } /* 郵便番号など、桁数が決まった入力欄 */
.prose-en { max-width: 65ch; } /* 欧文の読みやすい行の長さ */
.prose-ja { max-width: 40em; } /* 日本語は em(全角1文字ぶん)で数える */
日本語の全角文字は 1ch より幅が広い(およそ 2ch 弱)ので、日本語の行の長さは em で数えるのが簡単です。
lh:行の高さを基準にする
lh は、その要素の line-height の計算値です。文字 20px・line-height 1.6 の要素で 1lh は 32px でした。
.excerpt {
max-height: 3lh; /* ちょうど3行ぶん */
overflow: hidden;
}
.icon { height: 1lh; } /* 行の高さにそろえたアイコン */
rlh はルート要素の line-height を基準にした単位です。Chromium 141 では CSS.supports("width:1lh") と CSS.supports("width:1rlh") がどちらも true でした。
cqw・cqi:部品の幅に連動させる
コンテナクエリ単位は、ビューポートではなく祖先のコンテナの大きさを基準にします。
.card-wrap { container-type: inline-size; width: 600px; }
.card-wrap .inner { width: 50cqw; height: 10cqi; }
width=300px height=60px
コンテナの幅 600px に対して、50cqw が 300px、10cqi が 60px になりました。横書きでは cqw と cqi は同じ値です。サイドバーに置いても本文に置いても、その場所の幅に合わせて文字サイズや余白を変えられます。@container の書き方は「CSSコンテナクエリ」の記事で扱っています。
fr:グリッドの空きを分け合う
fr は長さではなく、グリッドの中で残った空きスペースを分け合う比率です。
.grid { display: grid; grid-template-columns: 200px 1fr 2fr; width: 800px; }
1列目 width=200px 2列目 width=200px 3列目 width=400px
800px から固定の 200px を引いた残り 600px を、1:2 で分けています。fr は grid-template-columns などグリッドのトラック指定でだけ使えます。
html { font-size: 62.5% } は使うべきか
62.5% 指定とは
rem の計算を楽にするために、ルートの文字サイズを 10px 相当にする書き方です。16px × 62.5% = 10px なので、1.6rem が 16px、2.4rem が 24px と、10 で割るだけで換算できます。
html { font-size: 62.5%; } /* 1rem = 10px 相当 */
body { font-size: 1.6rem; } /* 本文を 16px 相当に戻す */
% で書いているので、ブラウザの文字サイズ設定には連動します(html { font-size: 10px } と px で書くと連動しなくなります)。
実測:body の指定を忘れると全体が 10px になる
Chromium 141 で 62.5% を指定した結果です。
html の font-size : 10px
font-size: 1.6rem の段落 : 16px
body(font-size を指定していない) : 10px
body に font-size: 1.6rem を書き忘れると、サイズを指定していない文字がすべて 10px になります。また、外部の CSS ライブラリや埋め込み部品は「1rem = 16px」を前提に作られていることが多く、62.5% のページに入れると全体が小さく表示されます。
実測:メディアクエリの em・rem は 62.5% の影響を受けない
もう1つ知っておきたいのが、メディアクエリの中の em と rem は、html の font-size ではなく、ブラウザの既定の文字サイズを基準にするという点です。画面幅 1000px、html { font-size: 62.5% } の状態で確かめました。
(min-width: 62.5em) -> true 62.5 × 16 = 1000px と判定された
(min-width: 62.5rem) -> true rem でも 16px 基準
(min-width: 100em) -> false 100 × 10 = 1000px とはならない
(min-width: 1000px) -> true
(min-width: 1001px) -> false
本文では 1rem = 10px なのに、メディアクエリでは 1rem = 16px として計算されます。62.5% を使うと、本文とメディアクエリで rem の換算が変わることになります。
判断の目安
| 観点 | 62.5% を使う | 使わない(1rem = 16px のまま) |
|---|---|---|
| px からの換算 | 10 で割るだけ | 16 で割る(CSS 変数や Sass の関数で補える) |
| 外部ライブラリとの相性 | 1rem = 16px 前提のものは小さく表示される | そのまま使える |
| body の指定 | font-size: 1.6rem が必須 |
不要 |
| メディアクエリ | 本文と換算がずれる | 同じ換算 |
新しく作るサイトでは、62.5% を使わず 1rem = 16px のままにしておくのが扱いやすい選択です。換算の手間は、よく使う値を CSS 変数にしておくと解消できます。
:root {
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 1rem; /* 16px */
--space-4: 1.5rem; /* 24px */
--space-5: 2rem; /* 32px */
--text-sm: 0.875rem; /* 14px */
--text-md: 1rem; /* 16px */
--text-lg: 1.25rem; /* 20px */
--text-xl: 1.5rem; /* 24px */
}
すでに 62.5% で作られているサイトは、そのままの方針でそろえて書くのが安全です。途中で基準を変えると、すべての rem の値を書き換えることになります。
px と rem の換算表も置いておきます(1rem = 16px のとき)。
| px | rem | px | rem |
|---|---|---|---|
| 4px | 0.25rem | 20px | 1.25rem |
| 8px | 0.5rem | 24px | 1.5rem |
| 12px | 0.75rem | 32px | 2rem |
| 14px | 0.875rem | 40px | 2.5rem |
| 16px | 1rem | 48px | 3rem |
| 18px | 1.125rem | 64px | 4rem |
メディアクエリの単位:px か em か
メディアクエリの幅は px で書くことが多いですが、em で書くと、ブラウザの文字サイズ設定に合わせて切り替わる位置も動きます。画面幅 1000px で、既定の文字サイズを変えて確かめました。
| ブラウザの既定の文字サイズ | (min-width: 48em) |
(min-width: 768px) |
|---|---|---|
| 16px | true(48 × 16 = 768px 以上) | true |
| 20px | true(48 × 20 = 960px 以上) | true |
| 24px | false(48 × 24 = 1152px 以上が必要) | true |
文字サイズを 24px にした利用者の画面では、em で書いたほうは「幅が足りない」と判定され、狭い画面用(1カラムなど)のレイアウトになります。文字が大きいぶん、1行に入る文字数が減っているので、狭い画面用のレイアウトに切り替わるほうが読みやすい場合が多くなります。
| 書き方 | 向いている場面 |
|---|---|
@media (min-width: 48em) |
文章中心のページ。文字サイズに合わせてレイアウトも切り替えたい |
@media (min-width: 768px) |
デザインカンプの px と合わせて管理したい。チームで px の表記にそろえている |
どちらを選んでも動作します。大事なのは、サイトの中でどちらかに統一することです。メディアクエリの中では rem も em も同じ基準(ブラウザの既定の文字サイズ)になるので、em で統一しておくと迷いません。
用途別の選び方表
ここまでの内容を、用途から引ける表にまとめます。
| 用途 | おすすめの単位 | 例 | 補足 |
|---|---|---|---|
| 本文・見出しの文字サイズ | rem | font-size: 1.125rem |
画面幅で変えるなら clamp() と rem + vw |
| 行間 | 単位なし | line-height: 1.7 |
子要素に倍率で引き継がれる |
| 字間 | em | letter-spacing: 0.05em |
文字サイズに比例 |
| セクションの余白 | rem | padding-block: 4rem |
サイト全体でそろう |
| 部品の内側の余白 | em または rem | padding: 0.5em 1em |
部品を拡大・縮小するなら em |
| 要素間のすき間(gap) | rem | gap: 1.5rem |
― |
| 線の太さ | px | border: 1px solid |
文字サイズに連動させない |
| 角丸 | px または em | border-radius: 8px |
部品に比例させるなら em、円は 50% |
| 影 | px | box-shadow: 0 2px 8px ... |
― |
| コンテンツの最大幅 | rem または em | max-width: 40em |
文字数で考えると読みやすい幅になる |
| カラムの幅 | %、fr | grid-template-columns: 1fr 2fr |
固定と可変の混在は fr が簡単 |
| 画像の幅 | % | max-width: 100% |
親からはみ出さない |
| 画面の高さいっぱい | svh / dvh | min-height: 100svh |
vh を1行前に書いておく |
| 画面幅に連動する大きさ | vw(clamp と併用) | clamp(1.5rem, 1rem + 2vw, 3rem) |
上限と下限を付ける |
| 部品の幅に連動する大きさ | cqi | font-size: clamp(1rem, 4cqi, 1.5rem) |
祖先に container-type が必要 |
| メディアクエリ | em または px | @media (min-width: 48em) |
サイト内で統一 |
| 印刷 | pt、mm | @page { margin: 15mm } |
@media print の中で |
よくあるつまずきと直し方
| 症状 | 原因 | 直し方 |
|---|---|---|
| 入れ子にすると文字がどんどん大きく(小さく)なる | font-size を em や % で指定している | rem に変える |
height: 100% が効かない |
親の高さが auto のまま | 親に高さを指定する、または Flexbox・Grid で高さを決める |
| スマートフォンで下端のボタンが隠れる | height: 100vh がツールバーの分だけはみ出している |
100svh か 100dvh に変える |
width: 100vw で横スクロールが出る |
100vw がスクロールバーの幅を含む | width: 100% にする |
| 文字サイズ設定を変えても文字が変わらない | font-size を px や vw だけで書いている | rem にする。vw は clamp() で rem と組み合わせる |
| 上下の余白を % で書いたら想定と違う大きさ | padding・margin の % は親の幅が基準 | rem や em で書く。比率の箱は aspect-ratio を使う |
| 62.5% のサイトで外部の部品が小さい | 部品が 1rem = 16px を前提にしている | 部品側の基準に合わせるか、部品を包む要素で調整する |
fr を width に書いても効かない |
fr はグリッドのトラック専用 | grid-template-columns などで使う |
単位を決めるときのチェックリスト
- 文字サイズは rem で書いたか(部品の中で比例させたい所だけ em)
- line-height は単位なしの数値にしたか
- 線・影など、文字に連動させたくないものは px にしたか
- 画面の高さいっぱいの指定に svh か dvh を使い、1行前に vh を書いたか
- vw を文字サイズに使う所は、clamp() で上限・下限と rem を組み合わせたか
- % を使った所は、何に対する割合かを確認したか
- ブラウザの文字サイズ設定を「大」にして、レイアウトが保たれるか確かめたか
計算値を自分で確かめる方法
単位が最終的に何 px になったかは、DevTools の「要素」パネルの「計算済み(Computed)」タブで見られます。JavaScript なら getComputedStyle() で取得できます。この記事の実測値も、同じ方法で取っています。
// コンソールに貼って実行:選択中の要素($0)の計算値を表示する
const cs = getComputedStyle($0);
console.log(cs.fontSize, cs.width, cs.paddingTop, cs.lineHeight);
ある単位が 1 単位で何 px になるかを調べたいときは、調べ用の要素を1つ作って幅に指定すると分かります。
// 1rem・1em・1vh・1dvh・1ch・1lh が何 px かを一覧にする
const probe = document.createElement("div");
probe.style.position = "absolute";
document.body.append(probe);
for (const u of ["1rem", "1em", "1vw", "1vh", "1dvh", "1svh", "1ch", "1lh"]) {
probe.style.width = u;
console.log(u, getComputedStyle(probe).width);
}
probe.remove();
スマートフォンの実機で dvh と svh の差を見たいときも、このコードをリモートデバッグのコンソールで実行すると、ツールバーの状態ごとの値を確かめられます。
よくある質問
Q. rem と em、結局どちらを使えばよいですか? A. 基本は rem です。文字サイズ・余白・最大幅など、サイト全体でそろえたい値は rem で書きます。ボタンやバッジのように「文字を大きくしたら余白も同じ比率で大きくしたい」部品の内側だけ em を使う、という使い分けがおすすめです。
Q. px は使わないほうがよいのですか? A. px が向いている場面もあります。線の太さ(1px)、影、細かな位置合わせなど、文字サイズに連動させたくないものは px が自然です。文字サイズと、文字に合わせて広がってほしい余白・幅を rem や em にする、と分けて考えると選びやすくなります。
Q. 100vh と 100% の高さは何が違いますか? A. 100vh は「画面の高さ」、100% は「親要素の高さ」が基準です。100% は親の高さが決まっていないと効きませんが、100vh は親に関係なく画面の高さになります。スマートフォンでは 100vh がツールバーの分だけ大きくなるので、100svh か 100dvh を使うと画面に収まります。
Q. dvh と svh はどちらを選べばよいですか? A. 迷ったら svh です。svh は値が変わらないので、スクロール中に要素の高さが動きません。チャット画面やモーダルのように、常に見えている範囲ぴったりに合わせたいときだけ dvh を選びます。
まとめ
- 文字サイズと余白は rem、部品の内側で文字に比例させたい所は em、線や影は px が基本の使い分け
- em は入れ子で掛け算になる。 1.2em を4階層重ねると 16px が 33.1776px になり、rem なら 19.2px のまま(Chromium 141 で実測)
- % の基準はプロパティごとに違う。 上下の padding・margin も親の「幅」が基準、line-height は自分の文字サイズが基準
- ブラウザの文字サイズ設定に連動するのは rem・em・%。 px と vw 単独の指定は変わらないので、文字サイズには rem か clamp() を使う
- スマートフォンの 100vh はツールバーの分だけはみ出す。 ファーストビューは 100svh、常に画面ぴったりにしたい画面は 100dvh
- 62.5% 指定は、body の指定漏れ・外部ライブラリ・メディアクエリの換算に注意が必要。 新しく作るなら 1rem = 16px のままが扱いやすい
- 迷ったら計算値を見る。 DevTools の「計算済み」タブか getComputedStyle() で、最終的な px を確かめられる
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「CSS単位の使い分け|remとemの違い・vw・vh・px早見表」
株式会社RJCでは、CSS の単位やレイアウトの考え方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。