要件
- アイテム同士の間に線を引く
- アイテムの横幅は均一とする
- リストの外側に位置するアイテムは外側に線を引かない
- 線の幅やカラム数を変更して汎用的に使える
- 背景色のことを知らなくても成立する
以下の図のようなイメージです。
設計
最終的に以下の図のような実装になりました。
実装
HTML
<div class="wrapper">
<div class="list" data-column-count="3">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
実際はulやliでマークアップしたり、BEM(MindBEMding)でclass名をつけたりする場合もあると思いますが、ここでは重要ではないのですべてdivでマークアップしています。
CSS
:root {
--border-width: 1px;
--border-color: gray;
}
.wrapper {
width: 100%;
overflow: hidden;
}
.list {
display: grid;
transform: translate(var(--border-width), var(--border-width));
margin-left: calc(-1 * var(--border-width));
margin-top: calc(-1 * var(--border-width));
}
.list[data-column-count="2"] {
grid-template-columns: repeat(2, 1fr);
}
.list[data-column-count="3"] {
grid-template-columns: repeat(3, 1fr);
}
.list[data-column-count="4"] {
grid-template-columns: repeat(4, 1fr);
}
/*
data-column-countは必要なバリエーションを記述する想定ですが、
もっと汎用的な方法があるかもしれないです。
*/
.item {
border-right: var(--border-width) solid var(--border-color);
border-bottom: var(--border-width) solid var(--border-color);
}
すべての要素がbox-sizing: border-box;の前提です。
同じページ内で異なるスタイルの格子を引く場合は、変数の定義などで工夫が必要かもしれません。
まとめ
上記はあくまで一例であって、他にもっと良い方法や面白い方法があると思います。
実装方法には正解がなく、なかば結果オーライでも成立してしまうので、あとから「負債」になることも少なくありません。
負債と聞くとすこしギスギスしそう..ですが、その負債は「当時の実装者が試行錯誤した成果」と言えます。
そのうえで「こうしたらもっと良くなるかも」を一緒に考えていけると、楽しく開発ができるかもしれません。

