もう画像に逃げないコードを書こう!
見た目の凝ったデザインをコーディングする際、表示領域(以下:わかりやすく画面幅と書きます)の拡大縮小に合わせてレイアウトが崩れてしまって、デレクターさんやデザイナーさんから、「デザイン通りになんとかならない?」と言われた経験ありませんか?
そんなときは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という裏技も使えるので、そのテクニックは改めて別記事で書こうかと思います。
一長一短ある書き方の一つですが、ぜひお試しください!
