CSS基礎 ToolShare Lab / Guide

CSS単位の使い分け完全ガイド
rem・em・px・vw・clamp()

「font-sizeにpxを使っていいのか?」「remとemの違いがイマイチわからない」「vwで文字サイズを指定したらスマホで小さすぎる」——CSS単位の選択は地味だが、レスポンシブ対応・アクセシビリティ・保守性に直結する最重要判断の一つだ。この記事では、px・rem・em・%・vw/vh・clamp()の6種を場面別に使い分ける具体的な基準を、コピーして使えるコード付きで解説する。

読了時間: 約12分 更新日: 2026年3月19日

CSSの主要単位は px(固定値)、rem(ルート基準の相対値)、em(親要素基準の相対値)、%(親要素の幅/高さ比)、vw/vh(ビューポート基準)の5種。font-sizeにはrem、コンポーネント内paddingにはem、レイアウト幅には%、全画面表示にはvw/vhが基本。clamp(min, preferred, max)を使えばメディアクエリなしで流体サイズを実現できる。

CSSの単位を理解する

CSSで使える長さの単位は大きく絶対単位相対単位に分かれる。絶対単位はデバイスに関係なく常に同じサイズを表し、相対単位は基準となる値に応じて伸縮する。Web制作で実際に使うのは以下の6種+1関数がほぼ全てだ。

単位 種別 基準 代表的な用途
px 絶対 CSSピクセル(1/96インチ) border, box-shadow, 細かい装飾
rem 相対 ルート要素(html)のfont-size font-size, margin, padding
em 相対 親要素のfont-size コンポーネント内の余白・アイコンサイズ
% 相対 親要素のサイズ レイアウト幅, max-width
vw 相対 ビューポートの幅(1vw = 1%) 全幅セクション, ヒーローエリア
vh 相対 ビューポートの高さ(1vh = 1%) ファーストビュー, フルスクリーン
clamp() 関数 最小値・推奨値・最大値の3値 流体タイポグラフィ, レスポンシブ余白

ここからは各単位の特徴・適切な使い所・避けるべきケースを具体的なコードとともに見ていく。

px — いつ使うべきか

pxはCSSの絶対単位で、1pxは1/96インチ(CSSピクセル)に相当する。Retinaディスプレイでは1CSSピクセルが複数の物理ピクセルに対応するが、ブラウザがスケーリングを処理するためコード上は気にしなくていい。

pxを使うべき場面

pxが最適なのは「サイズが変わるべきではない」要素だ。ユーザーがブラウザのフォントサイズ設定を変更しても、ボーダーの太さや影の大きさまで比例して拡大してほしくはない。

/* pxが適切なケース */ /* 1. ボーダー: 1pxの線は1pxのまま表示したい */ .card { border: 1px solid #e2e8f0; border-radius: 8px; } /* 2. box-shadow: 影の広がりは固定が自然 */ .card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); } /* 3. outline: フォーカスリングは常に同じ太さ */ .button:focus-visible { outline: 2px solid #3b82f6; outline-offset: 2px; } /* 4. メディアクエリのブレイクポイント */ @media (max-width: 768px) { /* 768pxはビューポートの実サイズ基準 */ }

pxを避けるべき場面

font-sizeにpxを使うとアクセシビリティ上の問題が生じる。ブラウザの「フォントサイズ設定」はルート要素のfont-sizeを変更する仕組みだが、pxで指定されたテキストはこの設定に反応しない。視覚障害のあるユーザーがフォントサイズを「大」に設定しても文字が大きくならないのだ。

/* NG: font-sizeにpx */ .heading { font-size: 24px; /* ブラウザ設定で拡大されない */ } /* OK: font-sizeにrem */ .heading { font-size: 1.5rem; /* ブラウザ設定に連動して拡大される */ }

Point

WCAG 2.2の達成基準1.4.4(テキストのサイズ変更)では、テキストを200%まで拡大してもコンテンツや機能が損なわれないことが求められている。font-sizeにpxを使うとこの基準を満たせない可能性がある。font-sizeには必ずremを使うのが現代の鉄則だ。

rem — フォントサイズと余白の基準

rem(root em)はルート要素(html)のfont-sizeを基準とする相対単位だ。ほとんどのブラウザでデフォルトのルートfont-sizeは16pxなので、1rem = 16px が基本の換算になる。

/* ブラウザのデフォルト: html { font-size: 16px; } */ .text { font-size: 1rem; /* = 16px */ font-size: 1.25rem; /* = 20px */ font-size: 0.875rem; /* = 14px */ font-size: 2rem; /* = 32px */ } /* margin/paddingにもremが有効 */ .section { margin-bottom: 2rem; /* = 32px, フォントサイズに比例 */ padding: 1.5rem; /* = 24px */ }

62.5%テクニック(非推奨)

古い記事で見かける html { font-size: 62.5%; }(1rem = 10pxにする方法)は、計算が楽になる反面、サードパーティのライブラリやブラウザのデフォルトスタイルが壊れるリスクがある。現在はブラウザの開発者ツールで換算を確認できるため、62.5%テクニックを使う必要はない。

/* 非推奨: 62.5%テクニック */ html { font-size: 62.5%; /* 1rem = 10px */ } body { font-size: 1.6rem; /* 全体を16pxに戻す必要がある */ } /* サードパーティCSSが10pxベースで崩れる可能性あり */ /* 推奨: デフォルトの16pxベースをそのまま使う */ html { font-size: 100%; /* 1rem = 16px (デフォルトのまま) */ } .heading { font-size: 1.5rem; /* = 24px */ } .small-text { font-size: 0.875rem; /* = 14px */ }

remとpxの早見表

rem px(16px基準) よくある用途
0.75rem 12px キャプション、注釈
0.875rem 14px 小さめの本文、ラベル
1rem 16px 本文テキスト
1.125rem 18px リード文
1.25rem 20px h4相当
1.5rem 24px h3相当
2rem 32px h2相当
2.5rem 40px h1相当

em — コンポーネント内の相対指定

emその要素自身の(font-sizeプロパティ以外)または親要素の(font-sizeプロパティの場合)font-sizeを基準とする相対単位だ。remと名前が似ているが、基準が異なるため使い所がまったく違う。

/* emの基準の違い */ .parent { font-size: 20px; } .parent .child { font-size: 0.8em; /* 親の20px × 0.8 = 16px */ padding: 1em; /* 自身の16px × 1 = 16px */ margin-bottom: 1em; /* 自身の16px × 1 = 16px */ }

emの強み: スケーラブルなコンポーネント

emの真価は「font-sizeを変えるだけでコンポーネント全体がスケールする」ことだ。ボタンの余白やアイコンサイズをemで指定しておけば、サイズバリエーション(small / medium / large)をfont-size一行で切り替えられる。

/* emでスケーラブルなボタン */ .btn { font-size: 1rem; padding: 0.5em 1.2em; /* font-sizeに比例して伸縮 */ border-radius: 0.3em; /* 角丸もfont-sizeに比例 */ gap: 0.4em; /* アイコンとテキストの間隔 */ } .btn .icon { width: 1em; /* テキストと同じ高さ */ height: 1em; } /* font-sizeを変えるだけでサイズバリエーション完成 */ .btn_size_small { font-size: 0.75rem; } /* 全体が75%に */ .btn_size_medium { font-size: 1rem; } /* 基準サイズ */ .btn_size_large { font-size: 1.25rem; } /* 全体が125%に */

emの注意点: 入れ子の罠

emは累積する。font-size: 0.9emを指定したリストの中にさらにリストがあると、孫要素は0.9 × 0.9 = 0.81倍、ひ孫は0.9 × 0.9 × 0.9 = 0.729倍と、どんどん小さくなる。font-sizeの指定にはemではなくremを使うのが安全だ。

/* NG: font-sizeにem → 入れ子で累積する */ .list { font-size: 0.9em; } /* .list > .list → 0.81em、.list > .list > .list → 0.729em */ /* OK: font-sizeにrem → 常にルート基準 */ .list { font-size: 0.9rem; } /* どれだけ入れ子にしても0.9rem(=14.4px)のまま */

Point

emとremの使い分けは明快だ。font-sizeにはrem(ルート基準で予測しやすい)、padding・margin・border-radiusにはem(font-sizeに連動してスケール)。この2つを守れば大半のケースで困らない。

vw / vh — ビューポート基準の単位

vw(viewport width)とvh(viewport height)はブラウザの表示領域の幅・高さを基準とする単位だ。1vw = ビューポート幅の1%1vh = ビューポート高さの1% になる。

/* ファーストビューのヒーローセクション */ .hero { height: 100vh; /* ビューポートの高さいっぱい */ width: 100vw; /* ビューポートの幅いっぱい */ } /* 画面幅に応じたフォントサイズ */ .hero__title { font-size: 5vw; /* 画面幅1200px → 60px, 375px → 18.75px */ }

vwをfont-sizeに使うリスク

font-size: 5vw のように指定すると、画面幅に完全に比例してフォントサイズが変わる。一見便利だが、超大画面では巨大に、超小画面では極小になり制御が効かない。さらに、ブラウザのフォントサイズ設定が無効化されるためアクセシビリティの問題も生じる。

/* NG: font-sizeに単独でvw */ .title { font-size: 5vw; /* 4Kモニター(3840px): 192px — 巨大すぎる */ /* スマホ(375px): 18.75px — 小さすぎる場合がある */ /* ブラウザ設定のフォントサイズ拡大が効かない */ } /* OK: clamp()で上限・下限を設ける */ .title { font-size: clamp(1.5rem, 4vw + 0.5rem, 3.5rem); /* 最小24px、最大56px の範囲で流体変化 */ /* rem混在でブラウザ設定にも部分的に対応 */ }

100vhの罠(モバイルブラウザ)

モバイルブラウザでは、アドレスバーの表示/非表示で実際のビューポート高さが変動する。100vh はアドレスバーを含まない「大きいビューポート」を参照するため、アドレスバー表示時にコンテンツがはみ出す問題が長年あった。2023年以降、この問題を解決する新しい単位が追加されている。

単位 説明 サポート状況
svh Small Viewport Height(アドレスバー表示時の高さ) Chrome 108+ / Safari 15.4+
lvh Large Viewport Height(アドレスバー非表示時の高さ) Chrome 108+ / Safari 15.4+
dvh Dynamic Viewport Height(リアルタイムで変動) Chrome 108+ / Safari 15.4+
/* モバイル対応のフルスクリーン */ /* 従来の方法(アドレスバーで崩れる可能性) */ .fullscreen { height: 100vh; } /* 推奨: dvhを使い、100vhをフォールバックに */ .fullscreen { height: 100vh; /* フォールバック */ height: 100dvh; /* 対応ブラウザではこちらが優先 */ } /* ファーストビューはsvhが安全(最小の高さで確保) */ .hero { min-height: 100vh; min-height: 100svh; }

% — 親要素に対する相対値

%親要素のサイズを基準とする相対単位だ。ただし、何に対する%なのかはプロパティによって変わる——ここが%の最大の落とし穴になる。

プロパティ 基準
width 親要素の width: 50% → 親の幅の半分
height 親要素の高さ 親にheightが明示されていないと効かない
padding 親要素の(上下paddingも幅が基準) padding-top: 56.25% → 16:9アスペクト比
margin 親要素の(上下marginも幅が基準) margin: 0 auto → 中央寄せ
font-size 親要素のfont-size emと同じ動作(累積する)
transform: translate 自分自身のサイズ translateX(-50%) → 自身の幅の半分左に
/* %の実践的な使い方 */ /* レイアウト: max-widthで最大幅を制限 */ .container { width: 90%; /* 親の90%を使う */ max-width: 1200px; /* 最大1200pxで止める */ margin: 0 auto; /* 中央寄せ */ } /* 2カラムレイアウト */ .sidebar { width: 30%; } .main { width: 70%; } /* アスペクト比の維持(従来の方法) */ .video-wrapper { position: relative; padding-top: 56.25%; /* 16:9 = 9/16 × 100 */ } .video-wrapper iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /* 推奨: aspect-ratioプロパティ(モダン) */ .video-wrapper { aspect-ratio: 16 / 9; }

Point

padding-toppadding-bottom% を指定すると、基準は親の(高さではない)になる。これは仕様通りの動作で、かつてはアスペクト比の維持に利用されていた。現在は aspect-ratio プロパティが全モダンブラウザでサポートされているため、そちらを推奨する。

clamp() — 流体タイポグラフィの実装

clamp(最小値, 推奨値, 最大値)は3つの値を取るCSS関数で、推奨値が最小値〜最大値の範囲に収まるよう制約する。メディアクエリを書かずにビューポート幅に応じてフォントサイズや余白を流体的に変化させるために使う。2026年現在、全モダンブラウザ(対応率96%超)でサポート済みだ。

/* clamp()の基本構文 */ font-size: clamp(最小値, 推奨値, 最大値); /* 例: 見出しのfont-size */ h1 { font-size: clamp(1.5rem, 2.5vw + 1rem, 3rem); /* * 最小: 1.5rem (24px) — スマホでこれ以下にならない * 推奨: 2.5vw + 1rem — ビューポート幅に応じて滑らかに変化 * 最大: 3rem (48px) — デスクトップでこれ以上にならない */ }

推奨値の計算方法

推奨値(preferred value)には vw + rem の形式を使うのがベストプラクティスだ。vw単独だとブラウザのフォントサイズ設定が無効化されるが、remを加算すると設定に部分的に反応する。

/* 推奨値の設計パターン */ /* パターン1: 本文テキスト(控えめな流体変化) */ body { font-size: clamp(1rem, 0.5vw + 0.875rem, 1.125rem); /* 16px → 18px の間で緩やかに変化 */ } /* パターン2: セクション見出し(中程度の流体変化) */ h2 { font-size: clamp(1.25rem, 2vw + 0.5rem, 2rem); /* 20px → 32px の間で変化 */ } /* パターン3: ヒーロー見出し(大胆な流体変化) */ .hero-title { font-size: clamp(2rem, 5vw + 0.5rem, 4.5rem); /* 32px → 72px の間で変化 */ } /* パターン4: セクション間の余白 */ .section { padding: clamp(2rem, 5vw, 6rem) 0; /* 32px → 96px の間で変化 */ }

clamp()でメディアクエリを削減する

従来のレスポンシブ対応では、ブレイクポイントごとにfont-sizeやpaddingを切り替える必要があった。clamp()を使うと1行で済み、しかもブレイクポイント間の滑らかな変化が得られる。

/* 従来: メディアクエリで段階的に切り替え */ h1 { font-size: 1.5rem; } @media (min-width: 600px) { h1 { font-size: 2rem; } } @media (min-width: 1024px) { h1 { font-size: 2.5rem; } } @media (min-width: 1440px) { h1 { font-size: 3rem; } } /* clamp(): 1行で滑らかに変化 */ h1 { font-size: clamp(1.5rem, 2.5vw + 1rem, 3rem); }

ツールで効率化

clamp()の値を手計算するのは面倒だ。当サイトのCSS clamp()ジェネレーターなら、最小・最大のfont-sizeとビューポート幅を入力するだけで最適なclamp()式を自動生成できる。登録不要・完全無料。

場面別の使い分け早見表

最後に、プロパティ×単位の組み合わせを早見表にまとめた。迷ったらこの表を参照してほしい。

プロパティ 推奨単位 理由
font-size rem / clamp() アクセシビリティ(ブラウザ設定に連動)+ レスポンシブ
line-height 単位なし(1.5等) font-sizeの倍率として動作。emや%だと入れ子で崩れやすい
padding / margin rem / em remで全体統一、emでコンポーネント内スケール
width(レイアウト) % / fr 親要素やグリッドコンテナーに対する比率
max-width px / rem 「この幅を超えない」という絶対的な上限
height(フルスクリーン) dvh / svh モバイルのアドレスバー問題を回避
border px 線の太さはフォント拡大で変わるべきではない
border-radius px / em 固定ならpx、コンポーネントと連動させるならem
box-shadow px 影の広がりは固定サイズが自然
gap(Grid/Flex) rem / clamp() 全体の余白設計と統一。レスポンシブならclamp()
メディアクエリ px ビューポートの物理サイズに対する閾値

Point

line-heightは単位なしの数値(例: 1.5)で指定するのがベストプラクティスだ。line-height: 1.5emline-height: 150% は計算値が固定されて子要素に継承されるため、font-sizeが異なる子要素で行間が崩れる。単位なしなら常にfont-sizeの倍率として再計算される。

CSS単位を活用するツールを使ってみよう

clamp()の値を自動計算したり、CSS単位を相互変換したりできるツールを無料で提供している。登録不要でブラウザだけで使える。

よくある質問

font-sizeにpxを使うと何が問題ですか?
ブラウザの「フォントサイズ設定」が効かなくなる。視覚障害のあるユーザーがフォントサイズを拡大設定しても、pxで指定されたテキストは大きくならない。WCAG 2.2の達成基準1.4.4(テキストのサイズ変更)を満たせない可能性があるため、font-sizeにはremまたはclamp()を使うのが現代の鉄則だ。
remとemはどう使い分ければいいですか?
font-sizeにはrem(ルート基準で常に予測可能)、padding・margin・border-radiusなどコンポーネント内のサイズにはem(font-sizeに連動してスケール)を使い分けるのが定石だ。emをfont-sizeに使うと入れ子で累積するため避けたほうがいい。
vwをfont-sizeに使ってもいいですか?
vw単独でのfont-size指定は避けるべきだ。超大画面で巨大に、超小画面で極小になり制御が効かず、ブラウザのフォントサイズ設定も無効化される。代わりにclamp()を使って上限・下限を設け、推奨値にvw+remの形式を指定するのがベストプラクティスだ。
100vhがモバイルで正しく動かないのはなぜですか?
モバイルブラウザはアドレスバーの表示/非表示でビューポートの高さが変わるが、100vhは常に「大きいビューポート」(アドレスバー非表示時の高さ)を参照する。そのためアドレスバー表示時にコンテンツがはみ出す。解決策はdvh(動的ビューポート高さ)やsvh(小さいビューポート高さ)を使うことだ。100vhをフォールバックとして残し、100dvhを上書き指定するのが推奨パターンになる。
clamp()のブラウザサポートは十分ですか?
2026年現在、clamp()は全モダンブラウザ(Chrome 79+, Firefox 75+, Safari 13.1+, Edge 79+)でサポートされており、グローバルカバレッジは96%を超えている。IE11のみ非対応だが、IE11のサポートは2022年6月に終了しているため、新規プロジェクトでclamp()の使用に支障はない。