CSS講座 / 色と単位:px・em・rem・パーセントの基準

CSSの色は色名、16進数、rgb関数などで指定できます。長さの基準は単位ごとに異なり、pxはCSSピクセル、emは文字サイズ、remはルートの文字サイズを基準とし、パーセントの基準はプロパティによって変わります。

同じ色を色名・16進数・RGBで表す

teal、#008080、rgb(0, 128, 128)は同じ色です。RGBはRed・Green・Blueの略です。色名は定義済みの名前を使い、16進数やRGBは赤・緑・青の成分を数値で指定します。

rgb(0 128 128 / 20%)の20%は不透明度です。下の色が大きく透け、100%なら不透明になります。見える結果は下地によっても異なります。背景色にだけalphaを入れる方法と、要素全体へopacityを指定して文字や子まで半透明にする方法は違います。MDNの色のリファレンスで指定形式を確認できます。

px・em・remの基準を分ける

pxはCSSピクセルで、画面の物理ピクセルと常に一対一ではありません。機器の画素密度や表示倍率で見え方が変わり、16pxを指定してもブラウザーの拡大機能を妨げる意味にはなりません。

font-sizeのemは継承した文字サイズを基準とし、paddingのemはその要素自身の文字サイズを基準とします。remはルート要素の文字サイズです。親もルートも16pxなら、1.25emと1.25remはどちらも20pxです。その要素の文字が20pxならpadding:1emは20px、padding:1remは16pxになります。

font-size:1.25emを入れ子の各段へ指定すると16→20→25pxと増えます。同じ構造で1.25remなら二段とも20pxです。周囲の文字に比例する部品にはem、ページ全体で同じ基準を使うならremが便利です。どちらが常に正しいかではなく追従させたい基準で選びます。フォントと行の高さ、MDNの値と単位も参照してください。

パーセント幅の計算元を探す

width: 50%は通常、包含ブロックの内容幅を基準に計算します。font-size: 125%は親から継承する文字サイズが基準で、すべてのパーセントが同じ対象を見るわけではありません。

.wrapper { width: 100%; max-width: 640px; padding: 1rem; }

.inner { width: 50%; font-size: 1.25rem; padding: 1em; }

この例はborder-boxです。ルートが16pxで十分な幅があり枠がない条件では、外側の幅は640px、左右16pxずつのpaddingを引いた内容幅は608pxです。内側の50%は304pxとなり、その左右20pxずつのpaddingを引くと内容幅は264pxです。

窓を狭くすると外側も小さくなり、内側も新しい内容幅の50%へ再計算されます。304pxに固定される指定ではありません。max-widthは外側が640pxより広がらないための上限です。計算は要素の大きさとbox-sizingでも比較します。

一つのファイルで比較する

次の全体をUTF-8のunits.htmlとして保存します。色、入れ子の単位、幅の計算を同じファイルで確認できます。

<!doctype html>

<html lang="en">

<head>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>Comparing colors and units</title>

  <style>

    html { font-size: 100%; }

    * { box-sizing: border-box; }

    body { margin: 16px; font-family: sans-serif; line-height: 1.7; }

    .wrapper { width: 100%; max-width: 640px; padding: 1rem; background: #e9f7ef; }

    .inner { width: 50%; padding: 1em; font-size: 1.25rem; background: white; }

    .color-name { color: teal; }

    .color-hex { color: #008080; }

    .color-rgb { color: rgb(0, 128, 128); }

    .alpha { padding: 1rem; background: rgb(0 128 128 / 20%); }

    .nest { font-size: 16px; }

    .em-step { font-size: 1.25em; }

    .rem-step { font-size: 1.25rem; }

  </style>

</head>

<body>

  <h1>Colors and units</h1>

  <h2>Three notations of the same color</h2>

  <p class="color-name">Character specified by teal</p>

  <p class="color-hex">Characters specified as #008080</p>

  <p class="color-rgb">Character specified by rgb(0, 128, 128)</p>

  <p class="alpha">Only this box's background color has 20% opacity.</p>

  <h2>Width and spacing</h2>

  <div class="wrapper"><div class="inner">Text and padding in the inner box</div></div>

  <h2>Nested em</h2>

  <div class="nest"><div class="em-step">First step<div class="em-step">Second step</div></div></div>

  <h2>Nested rem</h2>

  <div class="nest"><div class="rem-step">First step<div class="rem-step">Second step</div></div></div>

</body>

</html>

htmlの100%はブラウザーの基準フォントに従うため、実習で16pxと仮定する前にComputedでhtmlのfont-sizeを確認します。基準が違う場合も同じ倍率で計算してください。

基準値を一つずつ変える

  1. ルートが16pxならemの入れ子が20px・25px、remが20px・20pxになるか確認します。
  2. 一時的にhtmlを20pxへ変えます。remの文字は25pxになり、固定16pxの.nest内のemは20px・25pxを保ちます。.innerのpaddingも25pxです。確認後はhtmlを100%へ戻します。
  3. 窓を広げ、元の16px条件で外側640px・内側304pxを確認します。窓を狭めると両方が小さくなることも見ます。
  4. 三つの色指定が同じRGB値になることと、.alphaの背景を変えても文字そのものが半透明にならないことを確認します。

違いが出たら、単位を変える前に親とルートの文字サイズ、padding、box-sizing、競合する規則を調べます。開発者ツールだけの一時変更は通常再読み込みで戻りますが、保存したファイルの値は自分で戻す必要があります。