こんにちは。今回は余白について書いていきます。
みなさんCSSにおいて余白といえばmargin、あるいはpaddingを思い浮かべるでしょう。要素と要素の間の余白はmarginを、要素の内側の余白にはpaddingを、というような使い分けをされます。
marginとpaddingの詳しい使い分けについては次の記事をご覧ください。
しかし、記事一覧ページのようにパーツがリストあるいはグリッド形式で並ぶ場合、各カード間の余白の付け方は、実は結構面倒です。
そういった場合にもdispaly: flex; もしくはdisplay: grid; とgapプロパティを組み合わせて非常に簡単で直感的に余白をつけることができます。
そんなgapプロパティについて解説していきます。基本編で使い方を解説し、詳細編でその原理やmarginと比較して何が優れているかなどを解説していきます。最後に、このようなコーディングテクニックを学ぶ上でおすすめの情報を紹介します。
基本編
gapプロパティはdispaly: flex; もしくはdisplay: grid; と併用することが前提なので、先にそれらについて触れておきます。
CSSレイアウトの進化
ここ数年、CSSによるレイアウトは大幅に進化しました。かつては要素を横並べにするだけでも一苦労で、floatプロパティを使ったりテーブルレイアウトを無理やり応用していた時代もありました。しかし、今はFlexboxとCSS Gridの登場により圧倒的にレイアウトの自由度と実装の簡易化が進んでいます。
例えば横に並べる場合はdispaly: flex; が簡単です。
<div class="Box">
<div style="flex: 1; background-color: red"></div>
<div style="flex: 1; background-color: orange"></div>
<div style="flex: 1; background-color: yellow"></div>
<div style="flex: 1; background-color: green"></div>
</div>
.Box {
width: 100%;
height: 120px;
display: flex;
}
格子状に並べるならdisplay: grid; を使いましょう。行の数と幅をgrid-template-columnsで定義し、列の数と高さをgrid-template-rowsで定義しています。
<div class="Box">
<div style="background-color: red"></div>
<div style="background-color: orange"></div>
<div style="background-color: yellow"></div>
<div style="background-color: green"></div>
</div>
.Box {
margin: auto;
width: 100%;
max-width: 400px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 120px 120px;
}
このように、flexとgridによりレイアウトは非常に自由になりました。Flexboxにおけるflex: 1; とGridにおける1frはそれぞれ特有の指定方法で、以下の特徴を持ちます。詳しくは後述しますが、非常に都合の良い指定です。
- 余った横幅にピッタリ広がる
- 指定されている要素が複数あったら均等に分け合う
この性質のおかげで各子要素が均等に横に並んでくれています。
ここにgapプロパティが組み合わさることで余白も自由自在になります。
gapプロパティの導入
上記の例にgapを追加してみましょう。親要素側にdisplay: flex; もしくはdisplay: grid; とあわせて使うことで適用されます。
Flexboxの場合
※HTML部分は同じなので省略
.Box {
width: 100%;
height: 120px;
display: flex;
gap: 20px; /* 追加 */
}
Gridの場合
※HTML部分は同じなので省略
.Box {
margin: auto;
width: 100%;
max-width: 400px;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 120px 120px;
gap: 20px; /* 追加 */
}
このように、gapプロパティは要素間の余白を非常に簡単に指定することができます。
さらにgapプロパティは縦方向と横方向の余白を分けて指定することもできます。縦方向を10px、横方向を40pxにしてみましょう。
.Box {
/* 省略 */
gap: 10px 40px; /* 縦の余白 横の余白 の順番で書く */
}
もしくは
.Box {
/* 省略 */
row-gap: 10px;
column-gap: 40px;
}
こうすることで次のように余白が表示されます。
簡単な上に縦横を個別に調整も出来て非常に便利です。
詳細編
marginよりgapが優れている理由
例えば記事一覧ページの要素を考えてみましょう。display: flex; で横並べにした時、もしmarginで余白をつけるとしたら、横方向の要素間の余白はどちらかの要素のmargin-left(margin-rignt)で実装することになります。次の画像のようになっていれば良いですね。
しかし、これを実現するにはnth-childを使ったりして煩雑なコードを書く必要があります。2列だった場合、例えば「偶数要素のmargin-left」という書き方になります。
.List-Card {
/* 省略 */
}
.List-Card:nth-child(even) {
margin-left: 20px;
}
これが2列ならまだ良いですが、3列以上になると面倒です。もちろんやりようはありますがコードはどんどん汚くなります。さらに列数が画面幅によって変わったりするともう大変。メディアクエリを何個も書かされるハメになります。
さらにこの場合、実は余白と.List-Cardのサイズを計算して出さないといけません。2列の場合、以下のコードは一見上手く行きそうに見えます。
.List-Card {
width: 50%;
/* 見た目については省略 */
}
.List-Card:nth-child(even) {
margin-left: 20px;
}
しかしこれは上手くいかず、2行になってしまいます。
これは、余白も含めた横幅が50% * 2 + 20px = 100% + 20px となってしまい親要素の横幅(100%)を超えてしまうからです。.List-Cardの横幅2つ分と余白の合計が100%に収まっていなければなりません。したがって次のような計算をする必要があります。
.List-Card {
width: calc((100% - 20px) / 2);
/* 見た目については省略 */
}
.List-Card:nth-child(even) {
margin-left: 20px;
}
さらに余白を20pxではなく24pxに変えたとしたらcalcの方も変えなければなりません。一応CSS変数を使って対応することはできますが。
さて、ここまで面倒な部分を見てきましたがgapを使えばこれら全てを気にする必要がありません。以下のように指定することで、列数や余白の幅がどうなろうと必ず「要素の間の余白は20px」になります。
.List {
width: 100%;
display: flex;
gap: 20px;
}
.List-Card {
flex: 1
/* 見た目については省略 */
}
Gridなら以下。
.List {
width: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}
.List-Card {
width: 100%;
/* 見た目については省略 */
}
レイアウトに関して、圧倒的にシンプルです。ぜひflex/gridとgapを組み合わせて使う方法を覚えてみましょう。
まとめ+おすすめ情報
というわけで、gapプロパティについてでした。要素の間に余白をつけたい時、marginでやると面倒だなという時はぜひgapを試してみてください。
このようにコーディングにおけるテクニックは日々進化していきますし、覚えるべき量も多いです。そこで案件で要求されやすいテクニックをまとめた本を書いていますのでぜひご覧ください!明日使えるテクニックばかりです。
コメント