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期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?