blog ブログ
こんにちは!デザイナーのasaです。
同じレイアウトでも人によってコーディング方法は様々です。コーディングしていると頻繁にでてくるカード型の記事などを複数並べるレイアウト。皆さんはどのようにコーディングしていますか?
おそらく「flexbox(フレックスボックス)」派と「grid layout(グリッドレイアウト)」派の2つに分かれると思います。
今回は 「flexbox」「grid layout」両方のやり方と、個人的に思う最適解を紹介します。
結論から知りたい方はこちらからどうぞ。
目次
カード型レイアウトのhtml
まずはhtmlを用意します。内容は一般的なサムネイル画像、タイトル、テキストで構成されたカード型リストです。
<ul class="card">
<li class="card__item">
<div class="card__img-area">
<img src="https://placehold.jp/300x200.png" alt="">
</div>
<div class="text-area">
<h3 class="card__title">タイトルタイトル</h3>
<p>テキストテキストテキストテキストテキストテキストテキスト</p>
</div>
</li>
<!-- 以下liを7回繰り返す -->
</ul>
「flexbox」の場合
まずは「flexbox」を使った作り方です。
コード全体は以下の通り。
.card {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card__item {
width: calc((100% - 60px) / 4);
background: #fff;
padding: 20px;
}
.card__img-area {
aspect-ratio: 3/2;
margin-bottom: 20px;
}
.card__img-area img {
width: 100%;
height: 100%;
object-fit: cover;
}
.card__title {
font-size: 20px;
font-weight: bold;
margin-bottom: 10px;
}
コードの解説
.card {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
親要素である.cardにdisplay: flex; で子要素を横並びにします。
さらに子要素がコンテンツ幅を超えたら折り返すようにflex-wrap: wrap;を指定します。
要素同士の間隔は「gap」を使用
例えば4カラムの場合、昔はカード要素にmargin-right、margin-bottomを指定し、右端(4の倍数)だけmargin-rightを0にするなど、あの手この手でやっていました。
しかし今は「gap」を使えば要素同士の間隔を簡単に指定できます。
子要素の幅を指定
.card__item {
width: calc((100% - 60px) / 4);
background: #fff;
padding: 20px;
}
子要素の幅指定のポイントはwidth: calc((100% – 60px) / 4);です。
4カラムで要素の間隔が20pxの場合、calc(100% / 4)では4番目がカラム落ちしてしまいます。なので要素同士の間隔20px × 3 = 60pxをひいた幅から4分割してます。
あとはメディアクエリ毎に3カラム、2カラムなどを指定してあげれば完成です。ただ子要素の幅の指定が若干めんどうかなと思います。
またflexboxだと、親要素にdisplay: flex;、子要素で幅指定と2つに分かれているのがちょっと気になるところです。(あくまで個人的意見です)
「grid layout」の場合
続いて「grid layout」 を使用したコードです。
コード全体は以下の通り。
.card {
display: grid;
grid-template-columns: repeat(4,1fr);
gap: 20px;
}
.card__item {
background: #fff;
padding: 20px;
}
.card__img-area {
aspect-ratio: 3/2;
margin-bottom: 20px;
}
.card__img-area img {
width: 100%;
height: 100%;
object-fit: cover;
}
.card__title {
font-size: 20px;
font-weight: bold;
margin-bottom: 10px;
}
コードの解説
.card {
display: grid;
grid-template-columns: repeat(4,1fr);
gap: 20px;
}
.cardにdisplay: grid;、grid-template-columns: repeat(4,1fr);を指定します。
「fr」は「fraction(比率)」の意味で、上記の場合1frを4回リピート(1:1:1:1)することになります。
grid-template-columns: 1fr 1fr 1fr 1fr;でも同じですがrepeat(4,1fr)と書いた方が可読性も上がります。
あとは「flexbox」同様メディアクエリ毎にカラム数を指定するだけです。「grid layout」は「flexbox」と違って親要素への指定だけで完結するので個人的にはこっちの方が使いやすいかなと思います。
以上が基本的なやり方ですが、「flexbox」「grid layout」どちらもメディアクエリ毎にカラム数を指定する必要はあります。これが常々めんどうだなと思っていました。
というのも大抵の場合、サイト構築時にブレークポイントを決めていると思います。4カラム、5カラムとなった場合初期のブレークポイントだけだとどうしてもレイアウトが崩れるので、このためだけにメディアクエリを追加しないといけない…なんてことがありました。
これらを踏まえて私が考える最適解のカード型レイアウトのコードを次に紹介します。
カード型レイアウトの最適解は「grid layout」にauto-fill&minmax
.card {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 20px;
}
ベースは「grid layout」を使用します。ただしカラム数を決めず、子要素の幅に応じて自動的に折り返すというものです。
minmax
minmaxでアイテムの最小幅と最大幅を指定します。今回のコードでいくと最小幅が200px、最大幅が1fr(可変)となります。
auto-fill
さらに繰り返しの部分にauto-fillを使うことで、アイテムが最小幅200pxを切るまでは余ったスペースをフィル(埋める)し、200px以下になるタイミングで折り返してくれるといった挙動になります。
このauto-fillとminmaxを使えば、わざわざメディアクエリ毎に分けて書く必要がありません。またコンテンツ幅に依存していないので流用もしやすいです。
auto-fill&minmaxを使ったサンプルがこちら↓
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
-
タイトルタイトル
テキストテキストテキストテキスト
まとめ
webの世界は日々アップデートされています。特にCSSはここ数年でどんどん進化している印象です。
これまで何行も書かないと実装できなかったものが、数行書くだけでできてしまうなんてことも少なくありません。常日頃からアンテナを張って乗り遅れないように心がけましょう。何より新しい機能を試すのは楽しいものですしね。
また弊社ではWEBやDTPの制作からマーケティングまでワンストップで対応していますので、お気軽にお問い合わせください。