はい。今回はタイトルの通り余白が生まれるタイミングは一体いつなのかを考えていきます。
これを理解すれば、marginとpaddingのどっちを使うのが正しいか、あるいは他の方法を使うべきかを判断する基準を持つことができると思います。
より質の高いコーダーになりたいという方はぜひ一緒に考えていきましょう。
余白は、レイアウトをするときに初めて生まれる
例えばこんなサイトがあったとします。
このサイトから、パーツと思われるものを取り出してみましょう。
ヘッダー
ファーストビュー
カード
サイドバー
フッター
おそらくこの5パーツが思い浮かぶかと思います。
この時点でお気づきかと思いますが、余白が消滅しています。
サイトのレイアウト時にあった各種余白は、パーツにバラした瞬間どこかに行っているはずです。上下左右に余白がある状態でパーツとみなすことはないですよね。
逆に、パーツを単純に敷き詰めると余白は無い状態で配置することになります。
このような配置のサイトは現実的にはあまり無いですよね。やはりレイアウト時に余白が生まれていると言えそうです。
コードとしてどう表現するか
まず、大前提として「使い回しが発生するパーツでなければそこまで気にしない」という風に僕は考えています。上記の例で言えば、カード以外はページ内で1回しか使っていません。その場合は普通にmarginでパーツ間の余白を指定すれば良いでしょう。
一方カードはそうもいきません。例えばカードにmargin-leftを付けると全要素に左方向の余白がつくわけですから、見た目が崩れます。
カード間の余白をつけようとしたら、このように左に余計な余白が生まれてしまいましたね。
だからこそ「偶数番目のみmargin-leftをつける」という形でnth-childなどの擬似セレクタを使う例がよく見られるわけですが、正直コードが煩雑になりあまり良い方法ではないです。今ならもっと良い方法があります。
可能な限り親要素側で余白を定義する
余白がいつ生まれるかを考えると、そもそもパーツ自身に外側の余白を持たせること自体があまり良くなさそうです。
ではどこで余白を定義するのが良いでしょうか。パーツを内包する親要素がレイアウトを行なっている、と考えてみましょう。
例えば次のようなレイアウトを行うとします。
flexないしはgridレイアウトを使っていれば、column-gap/row-gapというプロパティが使えます。
横方向の余白はcolumn-gap、縦方向の余白はrow-gapで指定します。
HTML
<div class="Container">
<div class="Container-Item"></div>
<div class="Container-Item"></div>
<div class="Container-Item"></div>
<div class="Container-Item"></div>
<div class="Container-Item"></div>
<div class="Container-Item"></div>
</div>
gridの場合のスタイル
.Container {
width: 100%;
display: grid
grid-auto-rows: auto;
grid-template-columns: 1fr 1fr;
column-gap: 30px;
row-gap: 20px;
}
.Container-Item {
width: 100%;
height: 300px;
background-color: #87ceeb;
}
flexの場合のスタイル
.Container {
width: 100%;
display: flex;
flex-wrap: wrap;
column-gap: 30px;
row-gap: 20px;
}
.Container-Item {
width: calc(50% - 30px / 2);
height: 300px;
background-color: #87ceeb;
}
このように、要素間の余白を親要素側が決めていますね。このような形であれば、.Container-Itemの方にnth-childで一部にのみ余白をつけたりする必要がありません。
また、このようなリスト表示でも応用できます。
これはマクドナルド公式サイト(https://www.mcdonalds.co.jp/)の新着情報のセクションです。
flexは縦方向のレイアウトも可能ですし、gridなら1列5行のgridと考えれば良いです。
親要素に以下のようなCSSの指定をするイメージです。
flexの場合
.Container {
width: 100%;
display: flex;
flex-direction: column;
row-gap: 20px;
}
gridの場合
.Container {
width: 100%;
display: grid;
grid-auto-rows: auto auto auto auto auto;
grid-template-columns: 1fr;
row-gap: 20px;
}
このようにすれば、ほとんどのレイアウトにおいて親要素から余白を定義することができます。
こうしておくことで、仮に子要素のクラスを複数の場所で使いたい時に余白が邪魔で困ることはありません。
ただし、この方法は各要素の余白が一定の場合のみ使えます。要素間の余白が全部一緒でない場合は他の方法を考えることになります。
dispaly: flexについてもっと詳しく知りたい方はこちらをご覧ください。
余白に関することは一切ユーティリティクラスに追いやる
これは僕もまだ検討段階の話なので、どの程度やるべきかは議論の余地があると思います。
具体的に何をやるかというと、「余白に関する情報は余白に関することのみを書いたクラス(=ユーティリティクラス)をつけることで対応する」ということです。
例えば次のようなコードを書くことになります。
<div class="Container">
<div class="Container-Item"></div>
<div class="Container-Item mt-4"></div>
<div class="Container-Item mt-8"></div>
<div class="Container-Item mt-4"></div>
<div class="Container-Item mt-2"></div>
<div class="Container-Item mt-12"></div>
</div>
.Container-Item {
//省略
}
.mt-2 {
margin-top: 8px;
}
.mt-4 {
margin-top: 16px;
}
.mt-8 {
margin-top: 32px;
}
.mt-12 {
margin-top: 48px;
}
このように余白はパーツのクラスとは完全に別のものにし、レイアウトを行うタイミングで余白を決めるような書き方です。これであればより自由にレイアウトを行え、かつパーツの見た目に影響しない形が実現できます。
一方見た目、レイアウトに関する情報が別のところに記述されることになるので見通しは少々悪くなりそうです。使いすぎは良くなさそうですね。
ただ前提でお伝えした通り「使い回しが発生するパーツでなければそこまで気にしない」という方針なのでこれが必要になる場面自体はあまり多くないと思われます。
まとめ
というわけで余白はいつ生まれるのか、ひいては余白をどうコードで扱うべきかを考えてみました。
レイアウト時に余白が発生するということと、パーツの中に余白などの外部の情報を含めるのはまずいということはかなり正しいかなと考えています。
また、もっと言えば余白の扱いに関してはデザイナーさんと協力して構築した方が良いでしょう。そもそも余白を統一したほうがコード上では質が上がるということを知らない方もいます。
逆にその上で余白をずらしたデザインが良いと判断されることもあります。
プロジェクトごとに何を持って良しとするかは微妙に変わってきます。「何が正解かを覚える」というより、そういう目線を持って取り組むということが一番大切です。
コメント