[CSS]レスポンシブ用にフォントのサイズと行の高さを可変で指定する極上テクニック -The math of CSS locks
Post on:2016年10月4日
CSS lockはレスポンシブWebデザインのテクニックで、フォントのサイズなどを指定した2つの値の間でスムーズに移行させることができます。レスポンシブのテクニックは通常、指定した値でフォントのサイズが急に変化しますが、常にビューポートの現在のサイズに依存して変化します。
レスポンシブ用にフォントのサイズと行の高さを可変で指定するテクニックを紹介します。
「math」とあるように、もう完全に数学です。
下記は各ポイントを意訳したものです。
検証やスタディ部分は省略しているので、元記事をご覧ください。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
CSS lockとは
ビューポートに対して相対的なサイズ
フォントのサイズを設定する時、小さいスクリーンサイズではより小さいテキストを、中くらいのスクリーンサイズでは中ぐらいのテキストを使用したいと思いませんか?
ビューポートの幅のサイズに対して、フォントサイズを相対的に指定することができれば、実現できます。
1 |
h1 { font-size: 4vw; /* これだけでいける? */ } |
しかし、このスタイルシートには2つの問題点があります。
- フォントは、小さいスクリーンサイズではで本当に小さく(320pxで12.8pxに)と大きなスクリーンサイズでは本当に大きく(1600pxで64pxに)なってしまいます。
- ユーザーはフォントのサイズをブラウザの設定で自由に変更できます。
CSS lockはこの1番目の問題を解決し、2番目の問題にも対応すべきです。
CSS lockのコンセプト
CSS lockとは、CSSの特定の種類の値を計算するテクニックです。
- 最小値と最大値を設定でき、
- 2つのブレイクポイント(通常はビューポートの幅に基づいた値)があり、
- それらブレイクポイントの間の値は、スムーズに移行。
上の図は、スクリーンサイズが320px以下の時は20pxで、960px以上の時は40pxで、その間は20pxから40pxに移行します。
CSSで書くとこんな感じです。
1 2 3 4 5 6 7 8 9 |
h1 { font-size: 1.25rem; } @media (min-width: 320px) { h1 { font-size: /* 『魔法の値』 from 1.25rem to 2.5rem */; } } @media (min-width: 960px) { h1 { font-size: 2.5rem; } } |
この1.25remから2.5remにスムーズに移行する『魔法の値』を決めることができれば、期待した通りに表示されます。
px単位のブレイクポイントを使ったCSS lock
px単位のブレイクポイントを使って、font-sizeとline-heightを指定
フォントのサイズについて考察
まずはフォントのサイズ、font-sizeについて、どのようにすべきか考察してみます。
ブレイクポイントを320pxと960pxに指定し、それぞれフォントのサイズを20pxと40px、その間はスムーズな移行で変化させるのがゴールです。
1 2 3 4 5 6 7 8 9 |
h1 { font-size: 20px; } @media (min-width: 320px) { h1 { font-size: calc( 3.125vw + 10px ); } } @media (min-width: 960px) { h1 { font-size: 40px; } } |
320px未満に20px、960px以上に40px、320-960pxはビューポートの単位vwをベースに算出します。「3.125vw」は、「フォントの増加分 / ビューポートの増加分」で、「(40 - 20) / (960 - 320)」から算出された値です。
px単位のサイズ指定は、使い勝手があまりよくありませんが、期待通りの結果で表示されます。
ユーザーがブラウザでサイズを変更した際にも対応
一般的なブラウザのデフォルトのフォントサイズは、16pxです。この値を小さくしたり、大きくしたり、ユーザーは自由に変更できます。このユーザーが変更したサイズに対応するために、サイズ指定の単位にremを使用します。
remはルートで設定したフォントのサイズを基準に、各サイズを算出する単位です。
ルートのサイズが16pxの場合、20pxは1.25remになり、上記のCSSをremに変更すると下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * 単位をremに変更 * • 0.625rem = 10px * • 1.25rem = 20px * • 2.5rem = 40px */ h1 { font-size: 1.25rem; } @media (min-width: 320px) { h1 { font-size: calc( 3.125vw + .625rem ); } } @media (min-width: 960px) { h1 { font-size: 2.5rem; } } |
この指定方法はルートが16pxの場合はうまくいきますが、ルートの値を変更するとうまくいきません。
ブルー:ルートが16px、レッド:ルートが24px
ルートが24pxの場合、ブレイクポイントが320pxの時にはフォントが30pxより一旦小さくなり、960pxの時には急に大きくなってしまいます。
この問題を解決するためには、移行を算出する際にベースの値を加えます。
1 2 3 4 5 6 7 8 9 |
h1 { font-size: 1.25rem; } @media (min-width: 320px) { h1 { font-size: calc( 1.25rem + 3.125vw - 10px ); } } @media (min-width: 960px) { h1 { font-size: calc( 1.25rem + 20px ); } } |
「1.25rem」をベースの値に加えることで、320pxから960pxのグラフの線をその分上げ、スムーズな移行になります。
パープル:手を加えていないサイズ、ブルー:ルートが16px、レッド:ルートが24px
ユーザーがブラウザでフォントのサイズを変更した時に、期待通りの結果ではないかもしれませんが、ビューポートに対して相対的にサイズを変更できます。
行の高さについての考察
フォントのサイズをビューポートに対して相対的に指定できたので、line-heightもそれに合わせて変更させる必要があります。320pxでは140%に、960pxでは180%にしてみます。
1 2 3 4 5 6 7 8 9 |
p { line-height: 140%; } @media (min-width: 320px) { p { line-height: calc( 140% + 1vw - 3.2px ); } } @media (min-width: 960px) { p { line-height: calc( 140% + 6.4px ); } } |
320px未満に140%、960px以上に180%になるように140%をベースに6.4pxを加え、、320-960pxはビューポートの単位vwをベースに算出します。「3.2px」は、「フォントの増加分 / ビューポートの増加分」で、「(6.4 - 0) / (960 - 320)」から算出された値です。
この指定でline-heightは、下記のように移行します。
ブルー:ルートが16px、レッド:ルートが24px
計算を自動化
ここまでの計算では、ベースとなる値から手動で算出する必要がありました。この計算を自動化します。
フォントサイズを例に、計算式をすべて書いてみます。
1 2 3 4 5 6 7 8 9 10 11 12 |
@media (min-width: 320px) and (max-width: 959px) { h1 { font-size: calc( /* y1 */ 1.5rem /* + m × x */ + ((40 - 24) / (960 - 320)) * 100vw /* - m × x1 */ - ((40 - 24) / (960 - 320)) * 320px ); } } |
冗長な箇所があるので、簡潔にしてみます。
1 2 3 4 5 |
@media (min-width: 320px) and (max-width: 959px) { h1 { font-size: calc( 1.5rem + 16 * (100vw - 320px) / (960 - 320) ); } } |
line-heightも同様に簡潔に自動化してみます。
1 2 3 4 5 6 7 |
@media (min-width: 320px) and (max-width: 959px) { h1 { font-size: calc( 1.5rem + 16 * (100vw - 320px) / (960 - 320) ); /* For a negative slope, we have to invert the breakpoints */ line-height: calc( 120% + 3.2 * (100vw - 960px) / (320 - 960) ); } } |
em単位のブレイクポイントを使ったCSS lock
em/rem単位のブレイクポイントを使って、font-sizeとline-heightを指定
px単位のスムーズな変更が完成したので、em/rem単位で同様に移行するように指定してみます。
emベースのブレイクポイント
emベースで2つのブレイクポイントを、20emと40emを設定した場合、下記を意味します。
- ベースフォントが16pxだと、320pxと960px
- ベースフォントが24pxだと、480pxと1440px
- など
※この値はデバイスのピクセルではなく、CSSにおけるピクセルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
h1 { font-size: 1.25rem; } @media (min-width: 20em) { h1 { font-size: calc( 1.25rem + 1.25 * (100vw - 20rem) / (60 - 20) ); } } @media (min-width: 60em) { h1 { font-size: calc( 1.25rem + 1.25 * 1rem ); } } |
20emでは、20emと60em間でビューポートの幅に応じて0-1rem移行します。60emでは20px増加させたいので、1.25remをベースに20px分(20px=1.25rem)を変化に対応できるようにするためにcalcを使って指定します。
remベースの場合、pxペースとは異なり、ユーザーがベースフォントのサイズを50%増やした時は、すべてが50%増えます。
ブルー:ルートが16px、レッド:ルートが24px
20pxが50%増えて30pxになり、40pxも60pxになります。
em/remベースのline-heightの設定
ブレイクポイントがより大きいサイズの時ほど、line-heightの値を少なくするため、60emを基準に計算をします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
h1 { line-height: calc( 120% + 0.2 * 1rem ); } @media (min-width: 20em) { h1 { line-height: calc( 120% + 0.2 * (100vw - 60rem) / (20 - 60) ); } } @media (min-width: 60em) { h1 { line-height: 120%; } } |
CSS lockまとめ
最後に、2つのCSS lockの書式を確認しておきましょう。
- サイズを使うことができるプロパティのために、
- font-size, line-heightで、
- そして、pxベース、emベースのブレイクポイントのために。
ブレイクポイントの単位を何にするかは、重要な条件です。pxベースのブレイクポイントが人気が高いですが、どちらにも長所があります。1つ言えることは、emペースのメディアクエリを使うのであれば、フォントサイズやレイアウトにpx単位は避けるべきです。統一させた方がスムーズにいきます。
参考: emベースのメディアクエリ
emベースのメディアクエリの場合、ルートのフォントサイズをオーバーライドさせるべきではありません。CSS lockの書式がここにあります。
1 2 3 4 5 6 7 8 9 |
@media (min-width: 20em) and (max-width: 60em) { selector { property: calc( baseline_value + multiplier * (100vw - 20rem) / (60 - 20) ); } } |
multiplierはユニットがない状態で、remの期待される増加分の値です。0.75remの最大増加値は0.75になります。
pxベースのメディアクエリの場合、ルートのフォントサイズを変更することができます。そして2つの異なるCSS lockの書式を使うことができます。
1つ目は、emベースに似ています。
1 2 3 4 5 6 7 8 9 |
@media (min-width: 320px) and (max-width: 960px) { selector { property: calc( baseline_value + multiplier * (100vw - 320px) / (960 - 320) ); } } |
multiplierはユニットがない状態で、pxの期待される増加分の値です。12pxの最大増加値は12になります。
2つ目はブラウザにあまり依存せずに、ブラウザに値を渡す前に自身で計算します。
1 2 3 4 5 6 7 |
@media (min-width: 320px) and (max-width: 960px) { selector { property: calc( baseline_value + 0.25vw - 10px; ); } } |
0.25vwと-10pxは、SassやPostCSSであらかじめ計算される値です。
この最後の計算式は、(良いMixinを使用している場合を除き)少し難しくなるかもしれませんが、何の値を加えているかデバッグすることを簡単にします。
sponsors