calc()
やclamp()
関数など、CSSの計算式では、100vw
などから%
をうまく作れない。そのため、%
の基本フォント・サイズを描画領域に応じて決定することは難しいと考えていた。しかし、%
を作れなくても、100%
にピクセルを加える形でもいいことがわかった。そこで、最小で100%
、最大で125%
、その間は描画領域のサイズに応じてなめらかに上昇するという形の実装を、clamp()
関数を使って行った。
このウェブサイトでは既に導入されているので、上記変化を確認することができる。ユーザーがどのようなフォント・サイズ設定をしていても、なめらかに変化し、うまく動いているようだ。また、ズームしても問題なく動き、フォント・サイズの変更とズームを組み合わせてもちゃんと動く。「なんでもmin()
、max()
、clamp()
関数でやってみよう!」というのは、今だけは正しい姿勢かもしれない。
html {
font-size: 112.5%;
font-size: clamp(
100%,
(100vw - 640px) * 0.004 + 100%,
125%
);
}
フォント・サイズの最小値と最大値は、clamp()
関数の最小と最大を使うだけで、わかりやすい。フォント・サイズの上昇を開始するしきい値は、実装で640px
としている部分で行う。基本フォント・サイズが変わるので、それに影響を受けないpx
単位などで行う必要があるだろう。上がり方の調整は、実装で0.004
としている係数で行う。大きくすれば急激に、小さくすればゆるやかに上昇する。
真ん中の式はピクセルで出てきそうで不安だが、ユーザーの設定したフォント・サイズに加わるだけなので、それが尊重される方向で決まる。またこの実装そのままだと、例えば描画領域の幅が480px
の時、真ん中の式は負の値を出すが、最小値の100%
が使われるため、ユーザーの設定したフォント・サイズより小さくなったりはしない。
フォールバックは、しなければユーザーの設定に従うので、しなくてもいい。もしするなら、最小値と最大値の中間にしたりすると簡単だろう。この例だと112.5%
になり、既定のフォント・サイズのままだと18px
だ。個人的に一番好きなくらいの文字サイズというのもあるが、悪くない値だと思う。
実際の変化をたどってみよう。既定の16px
のままとすると、125%
は20px
になる。最大でそこまでなので、計算で決まるのは4px
分だ。これが0.004に当たるため、4px / 0.004 = 1000px
で到達する。つまり、描画領域が640px + 1000px = 1640px
で20px
になる。
じゃあユーザーがフォント・サイズを変更していたらどうだろう。Chromeの最小だと9px
で、125%
は11.25px
になり、計算で決まるのは2.25px
分だ。これが0.004に当たるので、2.25px / 0.004 = 562.5px
で到達する。つまり、描画領域が640px + 562.5px = 1202.5px
で11.25px
になる。
逆に大きくした場合も考えてみよう。Chromeの最大だと24px
で、125%
は30px
になり、計算で決まるのは6px
分だ。これが0.004に当たるので、6px / 0.004 = 1500px
で到達する。つまり、描画領域が640px + 1500px = 2140px
で30px
になる。
しかし、ユーザーの設定によって、上がり方が違うように思える。%
という観点では、最小では562.5px
しかかからないのに対して、最大だと1500px
かかっており、3倍近くかかっている。その一方で、px
という観点だと、どのサイズでも250px
増えるごとに、基本フォント・サイズが1px
上がっている。そう捉えると、上がり方は同じだとも言えるだろう。
上で「ユーザーの設定が尊重される方向」と、あいまいに書いたが、完全な尊重ではないかもしれない。その理由はユーザーがフォント・サイズを設定している時、それをベースにしてほしいか、それともそのサイズで必ず表示してほしいかの二通りの状況が考えられるからだ。前者なら、多分このclamp()
関数は受け入れてもらえる。でも後者の場合、ユーザーは大きくなることすら許せないかもしれない。
ユーザー解析では、ユーザーがフォント・サイズを変えていることはすぐにわかるし、無視できない数、存在することもすぐにわかる。でも、そのユーザーたちがなぜ変えているのかまではわからない。固定的なサイズを望むユーザーには、もしかすると、あの実装するのを毛嫌いされるJavaScriptを使ったフォント・サイズ変更機能の方が、オプト・インで選択できる優れた解なのかもしれない。こういった時に必要になるのが、インクルーシブ・デザインなのだなと、ぼんやり考えていた。