CSS
CSS3
Sass
レスポンシブ

font-sizeの単位をvwにしてデバイスサイズに合わせて拡縮する

スマートフォンのフォントサイズは固定でいいのか問題

スマートフォンのコーディングでpxなどの固定値を使うとiPhone6 plusなどの画面幅の広い端末でフォントサイズが小さく違和感を覚えることがないでしょうか。
フォントサイズだけではなくマージンやパディングなどでも同じことが言えるのですが、画像はmax-width: 100%などとしているため画面幅に応じてある程度大きくなるのに対し、フォントサイズなどを固定値でコーディングしてしまうと、画像や画面幅に比べて小さく見えてしまい、余白が目立ったり不自然なレイアウトに見えることがあります。
デザイナーの本来の意図を汲み取るのであれば、画面幅が広くなったときはフォントサイズなどもそれに応じて大きくなるのが一番良いのではないかと思っています。

(追記)
ただし、個人的にfont-sizeを拡縮できるようにして思ったのはどんなプロダクトでも推奨できるものではないなということです。場合によっては初期のcss読込の際に文字サイズなどがグッと変わるのをはっきり見てとれてしまうこともあり、font-sizeがpx固定で問題ないようなプロダクトであればそれが一番いいと今は思っています。本当にfont-sizeを拡縮する必要があるか、それは一部なのか全体なのか、
よく考えて導入することが大事だなと思いました。

最初にデモ

大きく2つの方法があります。

  1. sassのmixinを使用してvwの値を自動計算する
    https://jsfiddle.net/katsunory/pw18jeba/77/

  2. vwとcalcとremのあわせ技(全体に適用するならこっちの方がおすすめ)
    https://jsfiddle.net/katsunory/pw18jeba/76/

それぞれの詳しい説明は下で。

font-size: vwという解決方法

vwという単位は画面幅に応じてピクセル数が変わるもので、ウインドウサイズに応じたリキッドなコーディングをしたいときに便利です。
vwを使用すれば画面幅に応じたフォントサイズを簡単に実現することができます。

vwとは

vwとは、ビューポートの幅の1/100の大きさを持った単位である。
つまり、ビューポートが100pxなら1vwは1pxになる。
%と異なるのは、親要素ではなくビューポートを基準とした相対値になる点。
画面幅により大きさが拡縮されるので、幅の小さい端末は小さく、幅の大きい端末は大きく表示させたい場合などに相性がいい。
remはルートのfont-sizeを変更するだけでレスポンシブ対応できるが、vwならそれすら行う必要がない。

他に以下の単位もある。

単位名 説明
vw ビューポートの幅の 1/100(100vwで横幅いっぱい)
vh ビューポートの高さの 1/100(100vhで縦幅いっぱい)
vmax ビューポートの高さか幅の大きいほうの 1/100
vmin ビューポートの高さか幅の小さいほうの 1/100

320pxの横幅を基準にfont-sizeを指定する場合

10px〜16pxまで指定したい場合は以下の表のようになる。

px vw
10px 3.125vw
11px 3.4375vw
12px 3.75vw
13px 4.0625vw
14px 4.375vw
15px 4.6875vw
16px 5vw

これでデバイス幅が変わっても文字サイズもそれに合わせて大きくなるため、字切りなどがほぼ変わらない見た目にすることができる。
しかし、vwをfont-sizeに指定する場合、実際設定したいpx数とかけ離れた数値になりどのサイズを指定したか非常にわかりづらくなる。
また、これより大きいサイズをいちいち計算するのも手間がかかりすぎる。

そこでsassのmixinを使用し自動計算するようにする。
また、vwがサポートされてない場合はpx指定がされるようにする。
androidの4.2ではvwはサポートされていない。

(追記)
基準の画面幅を決めてfont-sizeをpxからvwに計算できるツール作りました。
px-vw-calculator

sassのmixinを使用してvwの値を自動計算する

scss
// 第一引数で基準となる画面幅のフォントサイズ、第二引数で基準となる画面幅を入力
@function get_vw($size, $viewport:320){
  $rate: 100 / $viewport;
  @return $rate * $size * 1vw;
}

@mixin fz_vw($font_size:10){
  font-size: $font_size * 1px;
  font-size: get_vw($font_size);
}

p{
  @include fz_vw(13);
}
css
p {
  font-size: 13px;
  font-size: 4.0625vw;
}

fz_vwの引数にfont-sizeのpx数を渡すことでいい感じにvwを指定できている。
また、vwがサポートされていないデバイスについてはpx数で代替している。

PCでのfont-sizeについて

モバイル端末ではこれでいい感じのfont-size指定ができるが、PCではこのfont-sizeでは大きすぎる。
また、そもそもPCでは画面幅に合わせてfont-sizeを変えることはしたくない。
メディアクエリ@media screen and (min-width)などでPC用のサイズを記述し解消する。

scss
p{
  @include fz_vw(13);
  @media screen and (min-width: 769px) {
    font-size: 30px;
  }
}

簡単にといってもわざわざsassのmixinを作成してうまくいくように調整しているので、もっと簡単にできる方法はないかなと思っていたところ最近のコリスさんの記事を読んでいい方法を知りました。
[CSS]「calc()」を使うとスゴイ便利!ページのレイアウト、要素やフォントのサイズ指定など実装テクニックのまとめ

vwとcalcとremのあわせ技

ルート(html)のfont-sizeをcalc(100vw / 32)とすることで、iPhone5などの画面幅320pxのときは基準のフォントサイズを10pxとし、ルートより下ではremを使っていくという方法です。
これであればルートのfont-sizeは画面幅に応じてvwによって変わり、ルートより下はremで記述することでルートの変更が適用されるという寸法です。

remを使用する際は通常html{font-size: 62.5%}とすることが多いですが、これはPCのブラウザで基準フォントサイズが通常16pxとなってるものを10pxにしてremの計算をしやすくするためのものなので、画面幅に応じた計算をする際は上記のような方法が良さそうです。
mixinを使うこともなく、またremはgulp-pleeeaseであれば過去のブラウザのサポートもしてくれるのでよりやりやすいと言えます。
また、font-sizeで例示していますが、marginやpaddingにも便利に使えそうです。

課題は対応ブラウザ

上記の方法ではvw、rem、calc()というモダンブラウザ以外ではサポートが微妙な記述を含んでいます。
調べるとremはIE9、Android4.2にも対応しているのでレガシーブラウザでもほぼいけそうですが、vwとcalc()はAndroid4.4未満では使用できません。
そもそもPCでは画面幅に応じたフォントサイズなどにはしないのでいいですが、Android4.4未満が対応できないのはきついんですよね(マジで切り捨てたい)。

参考URL

Viewport-Relative Headings with Sass