#space-betweenめっちゃusefulやけど。
カードUIを作りたい時に困った話。
2カラム横並びの場合
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
}
.wrap .item{
/* 50%←カードが2枚なので(100/2%)。んでカード間マージンを10(5×2)pxにする */
width:calc(50% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
3カラム横並びの場合
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
}
.wrap .item{
/* 33.3%←カードが3枚なので(100/3%)。 */
width:calc(33.3% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
みたいな感じで、1行の場合はカードのサイズ( .item の width )だけ
なんとかしてやればどうとでもなるけど
例えばカードの数が可変な場合
もちろん、横に無限に並べるわけにはいかんやん。
だから flex-wrap:wrap; を使って改行してやるねんよ。
flex-wrap:wrap;使ってみる
例えば、横3つで折り返す時。
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
<div class="item item04"></div>
<div class="item item05"></div>
<div class="item item06"></div>
<div class="item item07"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
/* 折り返す */
flex-wrap:wrap;
}
.wrap .item{
/* 3つ横に並べるので、1つあたり (100/3) = 33.3% */
width:calc(33.3% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
/* 4枚目以降は次のカラムなので上とのマージンを確保しとく */
.wrap .item:nth-child(n + 4){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
.item06{background-image: url("http://dora3.work/assets/img/illust/st_doku.png");}
.item07{background-image: url("http://dora3.work/assets/img/illust/st_vio.jpg");}
#5枚のカードを1行3枚表示させて折り返す時、悲しい結果になる。
こんな感じで。
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
<div class="item item04"></div>
<div class="item item05"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
width:calc(33.3% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
.wrap .item:nth-child(n + 4){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
いや、CSS的には正しい挙動やけど、絶対ちゃうやんってなる。
1行目はまぁええとして、
2行目が2枚しかカードがないのに space-between しようとしてるから
左右に均等配置されてまうねん。
だからカード要素のケツに一発疑似要素を仕込んでやるわけ。
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
<div class="item item04"></div>
<div class="item item05"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
width:calc(33.3% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
/* 同じサイズの疑似要素を仕込む */
.wrap::after{
content:"";
display: block;
width:calc(33.3% - 5px);
}
.wrap .item:nth-child(n + 4){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
つまり不足分の要素を入れてやればおkってこと。
2つ要素が空いてもうた場合
でも結局、空き個数分埋めてやればおkっていう原則に戻ると
なんかしらで空き要素を埋めてやったらいいって事。
ここでflexboxの真髄、order を使うねん。
具体的には、.warpにafterに次いでさらにbeforeを追加して
んでそのbeforeをケツにもって来たったらええわけ。
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
<div class="item item04"></div>
<div class="item item05"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
width:calc(25% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
.wrap::after{
content:"";
display: block;
width:calc(25% - 5px);
}
/* before疑似要素を追加して末尾に追加 */
.wrap::before{
order:1;
content:"";
display: block;
width:calc(25% - 5px);
}
.wrap .item:nth-child(n + 5){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
.item06{background-image: url("http://dora3.work/assets/img/illust/st_doku.png");}
5カラム並んだ時どうすんねん
というか、そもそも横に5つ並ぶデザインってユーザビリティ的にどないやねん!って感じもするけど…
そんなに一気に視認させられても感ある。
まぁそれは置いておいて、仰せのままにコーディングするなら
5カラム均等配置もできなあかんし。
普通にカードのサイズを5カラム( 20%(100/5) )にすると
なんかもうそれはそれで逆にいい感じになる。
でも、BAD!なので
さっきの原則に戻って、「空いてる分どうにかしてやる」という考え方に達すると
3個あいてるやんってなるけど
擬似要素はbefore,afterしかないから、そいつらで追加できんのは2つまで…
となると、もうDOMを追加するしかない…
<div class="wrap">
<div class="item item01"></div>
<div class="item item02"></div>
<div class="item item03"></div>
<div class="item item04"></div>
<div class="item item05"></div>
<div class="item item06"></div>
<div class="item item07"></div>
<div class="item empty"></div>
<div class="item empty"></div>
<div class="item empty"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
width:calc(20% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
/* 空要素 */
.wrap .item.empty{
display: block;
width:calc(20% - 5px);
}
.wrap .item:nth-child(n + 6){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
.item06{background-image: url("http://dora3.work/assets/img/illust/st_doku.png");}
.item07{background-image: url("http://dora3.work/assets/img/illust/st_hen.png");}
というか、サンプルみたいに .item で表示させる内容の中(.itemのchild)がなんも無いって事
実務ではあんまりなさそうやし、empty疑似クラスを使ってやった方が
わざわざ .empty とかクラスつけんでええからそっちのが楽そう。
こんな感じ↓
<div class="wrap">
<div class="item item01"><span></span></div>
<div class="item item02"><span></span></div>
<div class="item item03"><span></span></div>
<div class="item item04"><span></span></div>
<div class="item item05"><span></span></div>
<div class="item item06"><span></span></div>
<div class="item item07"><span></span></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
width:calc(20% - 5px);
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
/* empty疑似クラスで対応に変更した */
.wrap .item:empty{
display: block;
width:calc(20% - 5px);
}
.wrap .item:nth-child(n + 6){
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
.item06{background-image: url("http://dora3.work/assets/img/illust/st_doku.png");}
.item07{background-image: url("http://dora3.work/assets/img/illust/st_hen.png");}
#jsで力技できんちゃん?力こそパワー
ページ内に「ここは3カラムで改行」、「ここは5カラムで改行」みたいに複数あった場合、
わざわざやるの面倒くさいので、もうjsでごりごりやっちゃう。
jQueryで書いてるけど。
<div class="wrap js-jcBetween" data-column="5">
<div class="item item01"><span></span></div>
<div class="item item02"><span></span></div>
<div class="item item03"><span></span></div>
<div class="item item04"><span></span></div>
<div class="item item05"><span></span></div>
<div class="item item06"><span></span></div>
<div class="item item07"><span></span></div>
</div>
.wrap{
display: flex;
justify-content: space-between;
width: 600px;
margin-left: auto;
margin-right: auto;
flex-wrap:wrap;
}
.wrap .item{
height: 200px;
background-position: center top;
background-size:cover;
background-repeat: no-repeat;
}
.wrap .item:empty{
display: block;
}
.wrap .item.js-marginTop{
margin-top: 10px;
}
.item01{background-image: url("http://dora3.work/assets/img/illust/07_tori.jpg");}
.item02{background-image: url("http://dora3.work/assets/img/illust/01_usagi_03.jpg");}
.item03{background-image: url("http://dora3.work/assets/img/illust/09_ino.jpg");}
.item04{background-image: url("http://dora3.work/assets/img/illust/15_kani.jpg");}
.item05{background-image: url("http://dora3.work/assets/img/illust/14_sisi.jpg");}
.item06{background-image: url("http://dora3.work/assets/img/illust/st_doku.png");}
.item07{background-image: url("http://dora3.work/assets/img/illust/st_hen.png");}
$(function(){
$('.js-jcBetween').each(function(){
// 何カラムか取得
let column = $(this).attr('data-column');
// 親のサイズ
let wrapWidth = $(this).width();
// flexitem(カード) 一個あたりのサイズ
let itemWidth = (+wrapWidth / +column) - 5;
// 追加するアイテムの個数
let emptyItemCount = +$(this).children('.item').length - +column;
// 空の要素追加
var emptyElement = '';
for ( var i = 0, l = emptyItemCount; i <= l; i++ ) {
emptyElement += '<div class="item"></div>';
}
$(this).append( emptyElement );
// カードにサイズを付加
$(this).children('.item').width( itemWidth );
// 2行目以降にmargin-topを付加
$(this).children( '.item:gt(' + ( +column-1 ) + ')' ).addClass('js-marginTop');
});
});
ただこれやと、スマホの時も5カラムになっちゃうから、その辺スマホを分岐してカラムを決定する方がいいかも。