もう画像に逃げないコードを書こう!
見た目の凝ったデザインをコーディングする際、表示領域(以下:わかりやすく画面幅
と書きます)の拡大縮小に合わせてレイアウトが崩れてしまって、デレクターさんやデザイナーさんから、「デザイン通りになんとかならない?」と言われた経験ありませんか?
そんなときはvw単位
とcalc()関数
を使うとかんたんに画面幅に合わせてレイアウトを保ってくれる要素を作ることが出来ます。
「いや、流石に無理でしょこんなん…画像にしちゃいましょ?」と逃げてる人、メディアクエリを大量に設定してごまかしている人、ちょっと理解するのが難しいですが、以下を試してみてください!
結論を急ぎたい人へ
前置きはいいから結論を教えて!という人へ。
こちらの計算式にを使うと表示させたい画面幅
に対して表示したいピクセル数
を指定できます。
calc( 表示させたいピクセル数 vw/ 表示させたい画面幅 ÷100)
ん…分かりづらいですね、例を見てもらったほうがわかりやすいと思います。↓
例)
-
画面幅が
375px
のとき高さ(height)が540px
となるようにしたい。
height: calc(540vw / 3.75);
-
画面幅が
1400px
のとき幅(width)が766px
になるようにしたい。
width: calc(766vw / 14);
-
画面幅が
1920px
のとき上下の余白(margin)が66px
になるようにしたい。
margin: calc(66vw / 19.2) auto;
というように、これらを駆使することで画面幅〇〇pxのとき〇〇px
という相対的なサイズを指定できる様になります。
例えば、下記のように画面幅に合わせて丸の位置や、テキストのサイズだけでなく、padding
や、font-size
も上記の方法で値を設定してあげると画面幅に合わせて拡大縮小するようになり、画像を埋め込んだ時のような振る舞いをしてくれます。
デザインって画面幅1920pxとかで設計されてたりしますよね?
もう、上の式にそのまんま値を当てはめてCSSを書いていくと、レイアウトが画面幅に合わせて拡大縮小する絶対に崩れない要素
が書けてしまいます!
下記例では画面幅600pxの時を想定して書いておりますが、どの画面幅でも崩れずに表示されているので確認してみてください!
See the Pen 絶対に崩れないCSSの書き方 by Seiyokabure (@seiyokabure) on CodePen.
計算方法どうなってるの?
VWからおさらい
計算方法について書く前に、まずはvwについておさらいですが、
vw
はviewport(表示領域)の横幅100%
を100vw
として扱います。
要は見ているブラウザの幅を基準にサイズを決めてくれるんですね。
ということは、表示している幅が1000px
のとき、100vw
が1000px
、10vw
が100px
となり、1vw
は10px
となります。
ですので、
width: 10vw;
と指定した場合は要素の横幅は常表示領域の横幅に対して10%
の大きさで表示してくれます。
ただ、これを使いこなすのには画面幅が常に変わりゆく中で、vw
をいくつに設定したらいいのか?と言うのが悩みどころです。
計算方法
ということで、どの様にvwを計算したらよいかと言うのを書いていきます。
まずは1vw
あたりのpx
を出したいと思います。
例えば1000px
で表示している際の1vw
あたりのピクセル数
を出したいとなると100vw
で割れば良いですね。
1000px ÷ 100vw = 10px
となりますので1vw
で10px
となります。
これはかんたんですね。
10vw
のときのpx
を出したければ
10 × (1000px ÷ 100vw) = 100px
1vw
が10px
ですからそれの10倍
ですね。
じゃあ、逆に100px
のときのvw
を出したいときは?
100px ÷ (1000px ÷ 100vw) = 10vw
です。
となると、1000px
の表示領域の時、100px
となるwidth
を書きたい場合は
10vw
が答えです。
ということで計算できたらwidth: 10vw;
とCSSに書いてください。
上記の計算を毎回するならばvw
ですべて完結します。
めんどくさいですね…
calc()を使いたい
そこで上記のような面倒な計算をしてくれるのがcalc()関数です。
式を書けば自動で算出してくれる便利な関数ですね。
width: calc(2 + 1);
と書けば3
になります。
calc()に入れるためにはどうしたらいいかというと、
-
1vwの出し方は100vwで割るだけ、
(1000px ÷ 100vw) = 10px
-
10vwの出し方は1vwの10倍だから
(1000px ÷ 100vw) × 10vw = 100px
-
求めたいのは100px、上記の式を割り算にしたらいいですよね。
100px ÷ (1000px ÷ 100vw) = 10vw
-
演算子に変換して単位は一旦取ってしまいましょう。
100 / ( 1000 / 100 ) = 10
-
calc()にいれて、出力したい単位を入れましょう。
calc(100vw / ( 1000 / 100 ) )
-
上記の形で完成でも良いのですが、冗長なので自分は割り算をしてしまっています(保守のこと考えてない等、賛否両論あるかもですが、、、)
calc(100vw/10)
ということで1000px
のとき、100px
となるcalc()の計算は
calc(100vw/10)
となります!
最後に注意点
コチラはデザインを忠実に再現したいセクションだけ
というような限定的な使い方に留めたほうが良いです。
vwはスクロールバーのサイズを含まない…
その理由の一つ、vw
は厳密には画面幅、ではなく画面右側のスクロールバーも含めて計算しています。
一方で、width: 100%
と書いている場所はスクロールバーを除いた幅を計算しています。
そして厄介なのがWindowsとMacでスクロールバーの幅が変わります…ユーザーの設定にもよることもあります。
width: 100%;
で作っているセクションと誤差が出ることを理解し、width: 100vw;
を適用しているヒーロービューセクションだけとか、誤差が出ない様にCSSを当ててとか、使いこなすのには特性を理解した上で使ってください。
また、全ページこのcalc()関数で書いてしまうと保守する人が自分でない場合はわからなくなってしまいます。
コメントで式を書いといてあげるとか、工夫が必要です。
何はともあれ、コーディングの段階
で、デレクターさんやデザイナーさんと共有
し、事前に相談
しましょう。
とは言いつつも、メディアクエリで段階的に調整するよりは再現の精度がかなり高いものが作れます!
無限に大きく、無限に小さくなる…
そして最大の弱点は、画面幅に対してフォントサイズなどは無限に大きくなるし、無限に小さく(Chromeは10pxが最小に)なります。
こちらはmax-width
などを使うと良いですが、フォントサイズは無理です。
Sassを使うとmax-font-size
という裏技も使えるので、そのテクニックは改めて別記事で書こうかと思います。
一長一短ある書き方の一つですが、ぜひお試しください!