webサイト制作をしていると毎回思うことがcss設計と余白の問題。
LPなどの長年運用も積み重ねもないようなページであればあまり気にしなくてよいが、コーポレートサイトやwebサービスでデザインシステムを構築しないといけない時はどうしてもcss設計が必要となってきます。
css設計と長年格闘していると私は毎回この面倒な問題に当たってしまうのですが、同じように思う人はいませんでしょうか?
ラインハイトなどによる、この微妙な余白、どうしよう問題とは?
ラインハイトなどによる、この微妙な余白、どうしよう問題とは、例えば以下のようなものです。
『見出しレベル2』のデザイン(左)の上下の余白を100pxにしたい。『見出しレベル3』のデザイン(右)の上下の余白を同じ100pxにしたい。
同じ余白を使用するのでcssを共通化できると思い、共通化して運用していると、『見出しレベル2』のデザインは中のコンテンツが24pxのh2に対し、『見出しレベル3』のデザインは中のコンテンツが20pxのh3になっており、さらに最後に画像が入っていいます。
ご存じの通り、文章はラインハイトによって上下に余白が付いてしまいます。
その影響により、緑のpx値が共通化してcssから付けるmarginの値ですが、その値に対して赤のpx値が実際に再現したい余白(100px)とは異なる値になってしまっています。
同じ余白を再現するために同じmarginを使用しても、コンテンツの内容によって見た目上の余白の値が変化してしてしまうのです。
これに対応するために共通化せずに、各ページ、各パーツに合わせてcssを制作しているとcssが複雑化してしまい、管理が大変になってきます。
そこで解決策としてはじめはbootstrapのようにいくつかのmarginのパターンを用意し、そのclassを追加する事で対応していました。
解決策1:bootstrapのようにいくつかのmarginのパターンを用意する方法
bootstrapのようにいくつかのmarginのパターンを用意する方法とは以下のような形です。
@media screen and (max-width: 768px) { .mt-s-0 { margin-top: 0px; } .mt-s-1 { margin-top: 1px; } .mt-s-2 { margin-top: 2px; } .mt-s-4 { margin-top: 4px; } .mt-s-8 { margin-top: 8px; } .mt-s-12 { margin-top: 12px; } } @media screen and (min-width: 769px) { .mt-d-0 { margin-top: 0px; } .mt-d-1 { margin-top: 1px; } .mt-d-2 { margin-top: 2px; } .mt-d-4 { margin-top: 4px; } .mt-d-8 { margin-top: 8px; } .mt-d-12 { margin-top: 12px; } }
このように、あらかじめ各marginに対応したcssを用意し、classを付け替えることでmarginを変更するというやり方です。
class名の決め方はmaterialUIと同じ命名規則です。
- mt => margin-top
- d => ディスプレイ(パソコン)画面の時
- 数字 => 値
ただ、これだと以下のようなデメリットがありました。
- class名が増えてしまう
- 限られたmarginしか使用する事ができない
多くの場合はデザインルールをはじめに決めているので上記2つとも大きな問題ではならないのですが、他プロジェクトとなり、デザインルールが変わってしまうと、それに合わせて制作する必要があるということが面倒でした。
何とか、別のプロジェクトでも使用する事ができるよう、すべてのパターンをカバーしつつ、class名を最小限に抑えるにはどうしたらいいのだ。
と、考えたところ、ある案が浮かびました。
marginの数字を2進法で管理する
01の組み合わせで数を表現する2進法。
bootstrapはclassを付ける、付けないの2つのパターンの組み合わせでスタイリングしていく手法です。
これって何かにしているな…
あ、2進法か!
そう思いmarginも2進法を応用して管理できないかと試してみたところうまくいきました。
やり方はまず以下のようなcssを用意します。
.mt { --mt-value1: 0px; --mt-value2: 0px; --mt-value4: 0px; --mt-value8: 0px; --mt-value16: 0px; --mt-value32: 0px; @media #{$screenSize_sp} { &.mt--s-1 { --mt-value1: 1px; } &.mt--s-2 { --mt-value2: 2px; } &.mt--s-4 { --mt-value4: 4px; } &.mt--s-8 { --mt-value8: 8px; } &.mt--s-16 { --mt-value16: 16px; } &.mt--s-32 { --mt-value32: 32px; } } @media #{$screenSize_pc} { &.mt--d-1 { --mt-value1: 1px; } &.mt--d-2 { --mt-value2: 2px; } &.mt--d-4 { --mt-value4: 4px; } &.mt--d-8 { --mt-value8: 8px; } &.mt--d-16 { --mt-value16: 16px; } &.mt--d-32 { --mt-value32: 32px; } } margin-top: calc(var(--mt-value1) + var(--mt-value2) + var(--mt-value4) + var(--mt-value8) + var(--mt-value16) + var(--mt-value32)); }
2進数なので、1から32まで2のn乗づつのパターンを用意します。
これで、1pxから64pxまでのパターン1刻みであらわすことができるようになりました。
使い方は以下のようにします。
例えばmargin-top: 12pxとしたい時。
<div class="mt mt--d-4 mt--d-8">content</div>
12を2進数の冪数であらわすと4と8なので、mt–d-4とmt–d-8の2つのclassを組み合わせて使用する事で12pxを再現可能です。
2進数の計算方法はこちらの記事が参考になります。