📝

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

11 min read 4

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

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

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

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

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

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

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

結論

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

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

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

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

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 を使えばレスポンシブ対応が楽になる」というものです。実際、今回の話題のキッカケとなるツイートでは以下のようなことが語られていました。

フォントサイズをレスポンシブにしたい時に、 rem を使えばメディアクエリでルートのフォントサイズを変更すればいいだけなのでかなり管理が楽です。 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

https://medium.com/@vamptvo/pixels-vs-ems-users-do-change-font-size-5cfb20831773

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

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

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

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 の指定は px と rem どちらを使うべきか?」問題に対する僕なりの回答です。

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

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