Flexboxでマルチカラムレイアウトを実現するには「justify-content: space-between;」で「左右均等配置」するのが一般的な方法です。

しかし、この方法だと最終行の要素が足りない場合に、要素が左寄せにならず、左右に分かれてしまいます

 

以下の画像のようになります。

 

flexboxで左右均等配置

 

この問題の解決方法を書いていきます。

Flexboxでマルチカラムレイアウトが左右に分かれる問題の解決法

3カラムの場合(要素数が固定)

まずは「3カラム」を実現させるコード解決策を載せていきます。

 

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>test</title>
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
<section id="card">
  <div class="card__contents">
    <article class="card__block">
      <div><img src="images/card-img-01.jpg" alt=""></div>
      <h3>タイトル1</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-02.jpg" alt=""></div>
      <h3>タイトル2</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-03.jpg" alt=""></div>
      <h3>タイトル3</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-04.jpg" alt=""></div>
      <h3>タイトル4</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-05.jpg" alt=""></div>
      <h3>タイトル5</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
  </div>
</section>
<script src="https://code.jquery.com/jquery-3.4.0.min.js" integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg=" crossorigin="anonymous"></script>
<script src="js/my.js"></script>
</body>
</html>

 

style.css

.card__contents{
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
}
.card__contents{
	width: 1146px;
	padding: 0 30px;
	margin: 30px auto;
}
.card__contents::after{
	content: '';
	width: calc(100% / 3 - 20px);
	display: block;
}
.card__block{
	padding: 10px;
	margin: 0 0 30px;
	background-color: #dfdfdf;
	border-radius: 4px;
}
.card__block{
  width: calc(100% / 3 - 20px);
}
h3{
	margin: 20px 0;
	font-weight: bold;
}

 

解決策は、style.css12行目~16行目です。

マルチカラムレイアウトを囲む親要素に、「::after」疑似要素を付けて

最終行の末尾に空の要素を追加しています。

 

末尾に見えない要素が1個入るので、

左寄せになったように見せる事ができます。

 

Flexboxで左右均等配置しつつ最終行の要素を左寄せにする

 

この方法は、あらかじめ要素の個数が決まっている場合に限ります

初めから要素数が5個しかないと分かっている場合のみ、空の要素を入れて数を6個に合わせているのです。

 

それでは、要素の個数が不確定の場合はどうでしょうか?

 

例えば、

ブログの記事一覧などをマルチカラムレイアウトで表示する場合、記事の個数は不確定です。

ブログをカテゴリー別に検索した場合、何個の記事がヒットするかは不確定ですよね?

 

次は要素の個数が不確定の場合の解決策を書きます。

3カラムの場合(要素数が不確定)

jQueryを使って要素数を取得する事で対策します。

先程のHTMLを使い回して「CSS」を少し変えていきます。
 
my.js

$(function(){
  for(var n=0; n<=3; n++){
    if(($('.card__block').length) === ((n * 3) + 2)){
      $('.card__contents').append('<article class="card__block"></article>');
    }
  }
});

 
style.css

.card__contents{
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
}
.card__contents{
	width: 1146px;
	padding: 0 30px;
	margin: 30px auto;
}
.card__block{
	padding: 10px;
	margin: 0 0 30px;
	background-color: #dfdfdf;
	border-radius: 4px;
}
.card__block{
  width: calc(100% / 3 - 20px);
}
.card__block:empty{
	background-color: #fff;
}
h3{
	margin: 20px 0;
	font-weight: bold;
}

 

先程はCSSで空の要素を追加しましたが、

今回は、「my.js」というjqueryファイルを使って動的に空の要素を追加します。

 

my.js」の3行目で、「$(.card__block).length」を使って要素数を取得、

要素数が2個か、5個か、8個の場合のみ、空の要素1つ追加しています。

 

これにより、要素が2個しかない場合でも左寄せに対応します。

 

Flexboxで左右均等配置しつつ最終行の要素を左寄せにする

 

対応する行数を増やしたい場合は、

my.js」の2行目の「forループ」の回数を増やす事で対応してください。

 

 

style.cssでは、「::after」疑似要素で空の要素を増やす処理を削除(jQueryで代替)。

21行目~23行目「:empty」疑似要素を使って、jQueryによって追加した空要素のデザインを調整しています。

今回はbackground-colorを#fffに戻しています。

 


スポンサーリンク

4カラムの場合(要素数が固定)

まず初めに、4カラムで最終行の要素が不足している場合、

どういう現象が起きるのかを見てみます。

 

 

【要素が2個足りない場合】

 

最終行が左右に別れます。

 

4カラムの最終行が分かれる

 

 

 

【要素が1個足りない場合】

 

最終行が3カラムの均等な間隔に別れます。

 

4カラムのマルチカラムレイアウトで要素が1個足りない場合

 

 

解決法は、要素数が確定している場合

CSSの疑似要素で埋めていく方法が有効です。

 

 

それでは、「4カラム」を実現させるコード解決策を載せていきます。

 

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>test</title>
  <link rel="stylesheet" href="css/style.css">
</head>
<body>
<section id="card">
  <div class="card__contents">
    <article class="card__block">
      <div><img src="images/card-img-01.jpg" alt=""></div>
      <h3>タイトル1</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-02.jpg" alt=""></div>
      <h3>タイトル2</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-03.jpg" alt=""></div>
      <h3>タイトル3</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-04.jpg" alt=""></div>
      <h3>タイトル4</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-05.jpg" alt=""></div>
      <h3>タイトル5</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-06.jpg" alt=""></div>
      <h3>タイトル6</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-07.jpg" alt=""></div>
      <h3>タイトル7</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-08.jpg" alt=""></div>
      <h3>タイトル8</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-09.jpg" alt=""></div>
      <h3>タイトル9</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
    <article class="card__block">
      <div><img src="images/card-img-10.jpg" alt=""></div>
      <h3>タイトル10</h3>
      <div>
        Lorem ipsum dolor sit amet, consectetur adipiscing earticlet.
      </div>
    </article>
  </div>
</section>
<script src="https://code.jquery.com/jquery-3.4.0.min.js" integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg=" crossorigin="anonymous"></script>
<script src="js/my.js"></script>
</body>
</html>

 

sytle.css

.card__contents{
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
}
.card__contents{
	width: 1146px;
	padding: 0 30px;
	margin: 30px auto;
}
.card__contents::after{
	content: '';
	width: calc(100% / 4 - 22px);
	display: block;
}
.card__contents::before{
	content: '';
	width: calc(100% / 4 - 22px);
	display: block;
	order: 1;
}
.card__block{
	padding: 10px;
	margin: 0 0 30px;
	background-color: #dfdfdf;
	border-radius: 4px;
}
.card__block{
  width: calc(100% / 4 - 22px);
}
h3{
	margin: 20px 0;
	font-weight: bold;
}

 

 

解決策は、style.css12行目~22行目です。

マルチカラムレイアウトを囲む親要素に、「::after」疑似要素「::before」疑似要素を付けて、最終行の末尾に2個の空の要素を追加しています。

 

最終行が1要素だけ不足している場合は、

「::after」疑似要素のみで対応できます。

 

対策後は以下のように

左寄せの様に見せる事ができます。

 

flexbox4カラムの最終行を左寄せ

 


スポンサーリンク

4カラムの場合(要素数が不確定)

ブログのカテゴリ一覧などの様に、

マルチカラムレイアウトに表示する要素数が不確定の場合は、jQueryで対応します。

 

 

jQueryの追加と、「CSS」の内容を少し変えていきます。

 

my.js

$(function(){
  var lastBlock = $('.card__block').length;
  for(var n=0; n<=3; n++){
    if((lastBlock) === ((n * 4) + 2)){
      $('.card__contents').append('<article class="card__block"></article>')
                          .append('<article class="card__block"></article>');
    } else if((lastBlock) === ((n * 4) + 3)){
      $('.card__contents').append('<article class="card__block"></article>');
    }
  }
});

 

style.css

.card__contents{
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
}
.card__contents{
	width: 1146px;
	padding: 0 30px;
	margin: 30px auto;
}
.card__block{
	padding: 10px;
	margin: 0 0 30px;
	background-color: #dfdfdf;
	border-radius: 4px;
}
.card__block{
  width: calc(100% / 4 - 22px);
}
.card__block:empty{
	background-color: #fff;
}
h3{
	margin: 20px 0;
	font-weight: bold;
}

 

my.js4行目~6行目は、不足した2要素を追加する処理

7行目~8行目は、不足した1要素を追加する処理を行っています。

 

 

style.cssの「::after」「::before」はjQueryで代替したので削除。

21行目~23行目で、「:empty」疑似要素を使ってjQueryで追加した要素のデザインを調整しています。

 

 

flexboxの4カラムのマルチカラムレイアウト左寄せ

 

 

5カラム以上のマルチカラムレイアウトは、jQueryのみで対応していきます。

「ここまでしてFlexboxを使う意味があるのか?」と思ってしまいますが、実はもっと簡単な方法はあります。

 

要素間の余白が「px」固定の場合は、以下の方法を使った方がjQuery不要でラクです。

 

今回紹介した方法は、要素間の余白を「%」指定にした場合でも使えるので、

必要に応じて参考にして頂ければと思います。

 


スポンサーリンク