「font-sizeの指定はpxとremどちらを使うべきか?」問題に対する回答

公開:2020/12/13
更新:2020/12/15
9 min読了の目安(約8300字TECH技術記事 4

こんにちは。TAK(@tak_dcxi)です。

今回はSNSで頻繁に話題になる「font-sizeの指定はpxremどちらを使うべきか?」問題について。

自分が観測している限りだと、

  • font-sizeの指定はpxとremどちらを使うべきか?
  • Webデザイナーはコーディングの知識があったほうがいいか?
  • jQueryはオワコンなのか?
  • 実装者はピクセルパーフェクトに拘らないとダメか?
  • h1タグはどこに使うべきか?

あたりは四半期に一度は話題になっている感覚がありますね。

おそらくこの記事を読んでいる方や、もしくはタイムラインにこの記事のTwitterカードなんかが流れてきてウンザリしている方も多いことでしょう。僕も正直「またこの話題か…」という感想ですが、頻繁に話題になるということはそれだけ意見が割れているということなので、自分なりの見解をまとめるためにもこの記事を投稿することにしました。

この記事で語られていることはあくまでも「個人の見解」です。

結論

まず先に僕の中での結論から話すと「どっちでもいい」です。

と言うのもpxremどちらが向いているかというのは案件によってまちまちだからです。その案件がpxが向いているならpxを、remが向いているならremを使えばいいのです。

Webの世界には「font-sizeはremでなければならない」とかそういったルールはありません。あるのはそれぞれの現場です。pxrem、それぞれの特性を理解して向いている方を選択しましょう。

もっと言えばfont-sizeの種類にはpxremの他にもemvwなどがあり、どれにもメリットとデメリットはあります。要は使い分けではないでしょうか

CSSの主な単位についてのおさらい

「font-sizeの指定はpxとremどちらを使うべきか?」問題に対する具体的な見解に入る前に一旦CSSの主な単位についておさらいしておきましょう。というのもこの手の話題が出ると「そもそもremって何だよ」ってコメントを見かけるような気がするので。

原則的にfont-sizeに用いられる単位は「<length>データ型」と呼ばれるもので、これは長さの値を表す際に用いられる単位です。長さの単位なのでwidth, height, margin, padding, border-widthなどでも用いられます。<length>データ型は主に絶対指定と相対指定の2つのジャンルに分かれます。

絶対指定

どんな環境でも一定な物理的な長さ。例えば「30cm」は絶対指定ですが、日本にいようが宇宙にいようがその長さは「30cm」に変わりはありません。

相対指定

他の長さを基準として長さを指定することです。例えば同じ「70%」でも東京タワーの高さの70%と僕の身長の高さの70%では全然違いますよね。

よく見かける単位は以下の通りでしょうか。

単位 区分 説明
px 絶対 ディスプレイの画素「ピクセル」を1とする単位です。Retinaなどの高解像度モニターでは1pxが端末の複数ピクセルに変わることもあります。
pt 絶対 Web知らないデザイナーがイラレでカンプ作った時に見かけて困るやつ。 1ptは1インチの1/72相当で、1px=0.75ptです。
em 相対 font-size自身に使われる場合は親要素から継承されたフォントの大きさを表します。font-size以外で使われる場合はその要素が持つfont-sizeを基準とします。
rem 相対 「root em」の略でルート要素(html要素)のfont-sizeを基準とする単位です。原則的にはルート要素のフォントサイズの既定値は16pxなので、ルートのfont-sizeを弄っていない場合は1rem=16pxとなります。
% 相対 親要素の幅or高さを基準とする単位です。font-size自身に使われる場合は挙動はemと同じになります。
vw 相対 画面の横幅を基準とした単位です。1vwは画面の横幅の長さの1%。スクロールバーを含むのでwidthに指定する時は気をつけること。
vh 相対 画面の縦幅を基準とした単位です。1vhは画面の縦幅の長さの1%。font-sizeではあまり使われることのない単位です。iOSではアドレスバーの高さを考慮していないので100vhで画面の高さいっぱいに用いる時は気をつけましょう。
vmin 相対 画面の横幅と縦幅、どちらか狭い方を基準とした単位です。スマートフォンの縦持ちの場合はvw、横持ちの場合はvhと同じです。画面いっぱいのメインビジュアルの真ん中にロゴなどを配置する際にスマートフォンの縦向き・横向きで丁度よい大きさに調整するときなどに使います。
vmax 相対 画面の横幅と縦幅、どちらか広い方を基準とした単位です。スマートフォンの縦持ちの場合はvh、横持ちの場合はvwと同じです。利用用途はvminと同じです。
ch 相対 その要素に指定されているフォントの0の幅を基準とした単位です。CSSで1文字分余白を空けたりする時に使うかも。

remを使えばレスポンシブ対応が楽になる?

rem推奨派の意見で多いのが「remを使えばレスポンシブ対応が楽になる」というものです。実際、今回の話題のキッカケとなるツイートでは以下のようなことが語られていました。

font-sizeをレスポンシブにしたい時にremを使えばルートのfont-sizeをメディアクエリで変更すればいいだけなので管理がとても楽。pxで指定する場合は該当箇所を全部書き直さないといけない。メンテナンス性もコードサイズも悪くなるよね。

言いたいことは分かります。つまりはこういうことでしょう。

base.css
html {
  /* デフォルト(モバイルビュー)ではベースのfont-sizeは12px相当 */
  font-size: 75%;
}

@media screen and (min-width:768px) { 
  html {
    /* タブレットビューではベースのfont-sizeは14px相当 */
    font-size: 87.5%;
  }
}

@media screen and (min-width:1200px) { 
  html {
    /* デスクトップビューではベースのfont-sizeは16px相当 */
    font-size: 100%;
  }
}

レスポンシブの時にいい感じに調整したい箇所をremで指定し、ルートのフォントサイズを変えればremで指定した箇所も意図したように変わるためレスポンシブ対応が楽だということでしょう。確かに、ルートのフォントサイズを弄っただけでfont-sizeやfont-sizeを基準としたmarginpaddingがいい感じに変わる案件なら作業効率的にもコードの簡潔さ的にもベストな選択肢だと思います。

でも、ルートのフォントサイズを弄っただけでレスポンシブでも文字調整が済むデザインってそこまでありますか?

例えば見出しのジャンプ率を考慮しても僕が過去に携わってきた案件でデスクトップビューとモバイルビューでそれらが同じだった案件の数は0です。僕の見ている世界が狭いだけかもしれませんが、ルートのフォントサイズを調整すれば完結するような一律のフォントの設計になってる案件ってほぼほぼ無いと思います。

デザイン的に考えてもデスクトップビューの本文のデフォルトサイズが16pxで見出しのデフォルトサイズが24pxの場合、モバイルビューで本文のデフォルトサイズを12pxに変更したら見出しのフォントサイズは24×0.75で18px。12pxに対して18pxは大きすぎる印象です。

デフォルトのフォントサイズを弄るだけならbodyのfont-sizeの変更でも十分ですし、pxでもremでも結局の所レスポンシブでfont-size調整のコストは同じような印象です。

もっと言えば、レスポンシブでfont-sizeを調整したい場合はルートのフォントサイズを弄るよりもSassの変数やCSSカスタムプロパティを使って管理したほうが小回りも効いてメンテナンス性に優れているのではないでしょうか?

base.css
:root {
  /* デフォルト(モバイルビュー)ではベースのfont-sizeは12px相当、見出しのfont-sizeは16px相当に */
  --font-size-default: 12px;
  --font-size-headline: 16px;
}

@media screen and (min-width:768px) { 
  :root {
    /* タブレットビューではベースのfont-sizeは14px相当、見出しのfont-sizeは20px相当に */
    --font-size-default: 14px;
    --font-size-headline: 20px;
  }
}

@media screen and (min-width:1200px) { 
  :root {
    /* デスクトップビューではベースのfont-sizeは16px相当、見出しのfont-sizeは24px相当に */
    --font-size-default: 16px;
    --font-size-headline: 24px;
  }
}

body {
  font-size: var(--font-size-default);
}

.headline {
  font-size: var(--font-size-headline);
}

※IE11ではCSSカスタムプロパティは利用できないため、IE11対応が求められるのならSassの変数かPostCSSのpostcss-custom-propertiesを使って対応しましょう。

ただ、動的にルートのフォントサイズを解釈するというrem独自の機能を活かす点においてはレスポンシブでルートのfont-sizeを調整するというのはとても理に適った行為ではあります。「レスポンシブを楽にする」ためにルートのfont-sizeを調節するというのは疑問がありますが、「remを動的な変数として扱い、レスポンシブでそれぞれベースとなる単位をremに代入して、それを基にCSSを設計する」とするのなら優れたプラクティスだとは思います。(ただ、現実はそこまで意識できないことが多い)

ひとつ注意点としてはルートのfont-sizeを調整する際は%なりを使ったほうが良いです。pxで指定すると後述する「ブラウザの文字サイズ調節機能が作動しない」問題が起こってしまうので…。

font-sizeをpxで指定するとブラウザの文字サイズ調節機能が作動しない

font-sizeをpxで指定しないほうが良いと言われる理由のひとつに「font-sizeをpxで指定するとブラウザの文字調節機能が作動しない」というものがあります。Chromeだと「設定→デザイン→フォントサイズ」の項目ですね。

font-sizeにpxを用いてしまうとユーザーが上記の設定で選択したフォントサイズは無視されてCSSで指定した文字サイズが適用されてしまいます。もし訪れてくださるユーザーが視力的な都合で文字サイズを拡大するように設定している場合、pxだとそういったユーザーに優しくないサイトになってしまう可能性もあるでしょう。

👆 ブラウザの文字調節機能を使って比較してみよう

「文字調節機能を利用しているユーザーってレアじゃない?」って意見もよく聞きますが、2年前の古いデータにはなってしまうもののInternet Archiveの調査ではブラウザの文字サイズ調節機能を利用している人は約3%だそうです。現在の日本における割合は分からないものの、もし3%のユーザーが利用しているとなると想像以上に多い気はしますね。

■参考文献:Pixels vs. Ems: Users DO Change Font Size

ただ、拡大したい場合は文字サイズ調節機能よりも画面ズーム機能を使うって方も多いでしょうし、実際著名なサービス(GAFAに加えてMicrosoftの自社サイトやAirbnbも)はpxを使っています。先進国のほとんどではWebアクセシビリティの確保が法律で義務付けられており、特に米国ではWebアクセシビリティに関する提訴件数が非常に多いのにも関わらずです。なので、font-sizeがpxで指定されているからと言って「アクセシビリティ的に悪い!」とは言えないのでは?とも思います。

ただ、ユーザーの取れる選択肢は多いほうが良いので、現在メジャーなブラウザの持つ機能を無視するかどうかは各々の価値観に依るとは思います。

CSS設計完全ガイド著者の半田さんのpxorremに対するツイートですが、僕はこちらの意見に全面的に同意しています。

remだと案件によっては困る可能性も…?

アクセシビリティを意識するとpxで指定しないほうが良いというのはありますが、案件や現場の環境によってはpxで指定したほうが良いって場合もあります。

具体的には、

  • 納品後にクライアント側でCSSを弄る可能性がある場合
  • 大規模案件などでCSSの知識が乏しい方がアサインされる可能性がある場合

など。

実際、pxの方が慣れ親しんでいるのか直感的だという意見も確かで、ローンチ後の改修の作業効率性を意識するとpxの方が良い場合もあります。実際問題、CSSをよく知らない人にとっては「remって何だよ」って感じでしょうし、そこで作業効率が落ちるのならremがどうとか言ってられないです。

また、CSSに精通している人でも1rem=16px相当の計算でremを使っている場合、電卓がないと計算が煩わしくなって余計な時間を費やしてしまうというのも聞いたことのある話です。(もしクライアントやCSSの知識が乏しい人が弄る場合、発狂してしまうかもしれません)

こういった場合はおとなしくpxを使うか、remを使う場合は後述する2つの方法を試してみるのも手かと。

解決策その1: ルートのフォントサイズを62.5%にして1rem=10px相当にする

よくあるパターンです。

base.css
html {
  font-size: 62.5%;
}

ルートにfont-size: 62.5%を指定して、1rem=10px相当にすれば計算も簡単になります。

ただ、このパターンだとfont-size: 62.5%を指定していない外部のCSSをマージする時にそのCSSでemとかremとか使われていると崩れたりする可能性はあります。(逆に言えばfont-size: 62.5%を指定していない場合も、外部のCSSがfont-size: 62.5%で計算されているかどうか気をつけたほうがいいかもしれない)

正直ハック的なやり方であることは否めないものの、デメリットとしてはそれくらいで、やや直感的になるという点では効率的な方法ではないでしょうか。

(僕個人の感想としてはfont-size: 62.5%はハードコーディング感が出るやり方に感じてしまうのであまり好きではないです)

解決策その2: Sassのfunctionを使う

僕はこのやり方で記述しています。

tools/function/_rem.scss
@function rem($px) {
  @return ($px / 16) * 1rem;
}

このfunctionをグローバルで用意しておき、

component/_button.scss
.my-button {
  font-size: rem(14); /* font-sizeは14px相当にする */
}

のように呼び出せばコンパイル後は0.875remと自動計算してくれます。

デメリットとしてはSassを利用しているのでコンパイル後のCSSをクライアントが触るってなったら辛くなるということでしょうか。ただ、コンパイル後のファイルを弄る事自体が色々と問題を抱えているので別の議論が必要な気がしますね…。

px→remに自動計算してくれるPostCSSのプラグインもありますが、使ったこと無いのでコメントできません。

自分なりのfont-size指定方法

個人的な見解としては現場でremが使えるようなら、何を使うか迷ったら思考停止でremを使ったらいいとは思います。理由としてはremのデメリットは開発的都合しか無いからです。

僕はBEMでいうBlockのfont-sizeはrem、Elementのfont-sizeはemで指定するようにしています。Blockのfont-sizeはページ全体を基準にして、Elementはコンポーネントを基準にするという考え方ですね。

だから自分が案件で最も利用するfont-sizeの単位はremでもpxでもなくemかもしれないです。

まとめ

以上が「font-sizeの指定はpxremどちらを使うべきか?」問題に対する僕なりの回答です。

基本的にはpxremも変わらないです。ブラウザの文字サイズ調節機能を意識するか、開発の効率性を意識するかの違いだと思います。どちらを尊重するかは現場によって異なるので「どちらでもいい」です。

あと、初学者の方は難しいこと考えないでpxを使いましょう。こういった発展的なことはある程度知識がついてからで十分です。それと「remを使えばレスポンシブ対応が楽になる」という意見に参考になったとコメントする前に、どうしてremを使えばレスポンシブ対応が楽になるのかを考えてから判断してみると良いと思います…。(この記事に対しても同じことが言えますね)