中身の総数が偶数 or 奇数に変化する2カラム List UI で、 border をきれいに付与する方法
この記事で分かること
中身の総数が偶数または奇数に変化する、 2 カラム構成の List UI におけるスタイリングで、特に border
をきれいに付与する方法が分かります。
API から取得した値をリストに流し込むようなシチュエーションを想定しています。
先に結論
:nth 判定式 をおすすめします。
ul {
display: flex;
flex-wrap: wrap;
background-color: #f8f8f8;
}
li {
width: 50%;
border-bottom: 1px solid #ccc;
&:last-of-type {
border-bottom: none;
}
&:nth-of-type(odd) {
border-right: 1px solid #ccc;
/* 全アイテムが偶数だった場合の、最後から 2 番目の奇数要素 */
&:nth-last-of-type(2) {
border-bottom: none;
}
}
}
様々な攻略方法
今回のデザインおよび HTML の実装要件は、
- リスト(コンテナ)の上下左右には
border
をつけない - それぞれのセル同士は
border
で区切られる - リストは背景色を持っている
- 総数が奇数のときに、最後に空の li を生成してはならない
となっています。この border
処理が曲者なので、いくつかの攻略方法を考案します。
grid 式
display: grid;
と gap
、そして background-color
を用いてみます。
ギミックとしてはこうです。
-
display: grid;
で 2 カラム構成にする - ul に対して、
border
にしたい色と同一のbackground-color
を付与する -
border
にしたい太さと同一のgap
を付与する - li に背景色の
background-color
を持たせる
gap
の隙間から下地の background-color
を覗かせ、 border
っぽく見せてしまおうという技です。
……何か様子がおかしいですね……。
そうです、総数が奇数の場合に ul の background-color
が最後に表示されてしまっているんですね。
何も中身がないセルに対しても li
と同じ background-color
を付与するという技が使えればいいのですが、
記事の公開時点(2023/12/01)では grid
はそのようなスキルを保有していないようです…。
必ず総数が偶数になることが確定しているならこの方法も良さそうですが、奇数パターンもある状況であれば、最適な攻略法とは言えません。
::before + absolute 式
擬似要素と absolute
を用いてみます。
ギミックはこうです。
- ul の
::before
に、border
と同一のwidth
、background-color
、そしてheight
に 100% を持たせる - ul 自身に
position: relative;
を付与する - ul の
::before
にposition: absolute;
を付与して、left: 0;
right: 0;
margin: 0 auto;
で左右中央に配置する
::before
で縦方向の border
を再現してしまおうという実装です。
ぱっと見上手くいっているような…?もしや討伐成功?
しかしデザイン要件を思い出してください……今回は「コンテナの上下左右には border
をつけてはいけない」のです。
奇数パターンに至っては、隣に li 要素が存在しないため、なんとも中途半端な下 border
が付いてしまっていますね。スタイルデバフです。よって、これも適した攻略法ではありません。
:nth 判定式
最後に、 :nth
を用いた border
処理法を試してみましょう。
ギミックの解説をします。
- li は、まずは決め打ちで
border-bottom
を持たせる - li の
:last-of-type
(最後の要素)には、border-bottom
が付かないようにする - li の
:odd
(奇数)には、border-right
が付くようにする - li の
:nth-last-of-type(2)
(最後から 2 番目の要素)が:odd
(奇数)だったとき、border-bottom
が付かないようにする
手順 4 が特にポイントです。この指定がないと、総数が偶数だったとき、最後から2番目の要素に border-bottom
が付いてしまいます。(ぜひ CodePen でお試しください)
総数が偶数のとき最後から 2 番目の要素は必ず奇数になり、総数が奇数のときは最後から 2 番目の要素は必ず偶数になることを利用しています。
手順 2 で「最後の要素には border-bottom
を付けない」と指定しているため、総数が奇数のときは見た目がきれいに整うのですが、
もし手順 4 を記述しないと、あくまで「最後」の border-bottom
しか消されないので、総数が偶数になったとき、最後から 2 番目の要素にはぐれ border-bottom
が出現してしまうのですね。
この処理法であれば、偶数奇数どちらのパターンが来てもスタイルが崩れることはなさそうです!
(ここで高らかな勝利のファンファーレ)
おわりに
前提となる要件に沿った結果このような実装方法となりましたが、前提が変われば解法も変わるのではないかなと思います。
同じ要件で border
の扱いに困ってしまったとき、ぜひ :nth 判定式 をお試しいただけると嬉しいです。
Discussion