3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Flexbox】display:flex; justfy-content:space-betweenで左詰めしたい。

Posted at

#space-betweenめっちゃusefulやけど。
カードUIを作りたい時に困った話。

2カラム横並びの場合

f05f5244f7bedf60d798047c59574ff1.png

<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カラム横並びの場合

f3464c8c65578370355d3880f4b10267.png

<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つで折り返す時。

こんな感じで。
495a47f6ed32d36f781900f5920b6478.png

<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枚表示させて折り返す時、悲しい結果になる。
7c3dabee0cc5b607cb618ba79ab63745.png
こんな感じで。

<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");}

するとハッピーな結果に。
02e1b1ac1e995763451816fe434d8a16.png

つまり不足分の要素を入れてやればおkってこと。

2つ要素が空いてもうた場合

29729644d849338c6beb6e260bf06e32.png
悲しい結果に。

でも結局、空き個数分埋めてやればお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");}

2ed49cf661e762c52b22c27f0cac604d.png
ハッピーな結果に。

5カラム並んだ時どうすんねん

というか、そもそも横に5つ並ぶデザインってユーザビリティ的にどないやねん!って感じもするけど…
そんなに一気に視認させられても感ある。

まぁそれは置いておいて、仰せのままにコーディングするなら
5カラム均等配置もできなあかんし。

普通にカードのサイズを5カラム( 20%(100/5) )にすると
なんかもうそれはそれで逆にいい感じになる。
ac495ad9e6865648b48a671cfedca71c.png

でも、BAD!なので
さっきの原則に戻って、「空いてる分どうにかしてやる」という考え方に達すると
3個あいてるやんってなるけど
擬似要素はbefore,afterしかないから、そいつらで追加できんのは2つまで…
となると、もうDOMを追加するしかない…
d50205fc863845c99815c604761574df.png

<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カラムになっちゃうから、その辺スマホを分岐してカラムを決定する方がいいかも。

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?