【CSS】エリア両端はスペース無し、内部ボックスに均等スペースを空けて配置する2つの方法(左寄せ折返し)

エリアの両端はスペースなし、内部のボックスの左右に均等なスペース(10pxずつ)を空けて配置する方法をまとめます。これは、ブログなどのサムネイルを左寄せで折り返して配置する時等、溢れてボックスが送られるページで、かつエリアの両端にスペースを入れたくない場合に役立つと思います。ボックスは敢えて5つ設置し、flex-wrap:wrapにして溢れた状態にしておきます。

最終的にブレイクポイントで4段から3段、2段、1段組みに変化するようなCSSに仕上げます。

HTML

エリアの両端はスペースなし、内部のボックスの左右に均等なスペース(10pxずつ)を作ります。

<div class="content-body"> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div>

【方法1】横幅を計算してサイズを割り当てる

4つのボックスを均等に配置

ボックスの横幅の計算方法

全体の横幅100%に対して4つのボックスなので、「横幅」割る「ボックスの数」で1つのボックスのパーセンテージを出します。

  • 全体横幅100% / 4個ボックス =25%(1つ辺りのボックスのパーセンテージ)

さらに、各スペースは3箇所(10pxずつ設定)、なので「スペースの数」掛ける「スペース幅」割る「ボックスの数」でそれぞれのボックスから差し引く幅を出します。

  • 空きスペース3つ * 10pxずつ / 4個ボックス =7.5px(1つ辺りのスペースのサイズ)

「1つ辺りのボックスのパーセンテージ」と「1つ辺りのスペースのサイズ」を差し引くと1つ辺りのボックスの横幅が出ます。

  • 25% – 7.5px =1つ辺りのボックスの横幅

CSSは嬉しい事に、パーセンテージやピクセルを混在して記載できます。この計算をまとめてcalcを利用して書くととこんな感じになります。

  • width: calc(100% / 4 – 3 * 10px / 4);
.box { /*ボックスの横幅*/ width: calc(100% / 4 - 3 * 10px / 4); }

nthを使ってそれぞれ空きを指定

次に4つのボックスそれぞれの空きを指定していきます。

擬似クラスnth-of-typeを利用して、指定したセレクタを数えます。一番左側が1,5,9番目…になり、左から2番目が2,6,10番目…、左から3番目が3,7,11番目…、一番右側が4,8,12番目…になるように擬似クラスnth-of-typeを設定します。

  • 一番左側(1,5,9番目…)
    nth-of-type(4n+1)
  • 左から2番目(2,6,10番目…)
    nth-of-type(4n+2)
  • 左から3番目(3,7,11番目…)
    nth-of-type(4n+3) {
  • 一番右側(4,8,12番目…)
    nth-of-type(4n)

それぞれのn番目のスペースを指定します。結果的に一番右側以外同じですが、わかりやすいように敢えて記載します。

/*1,5,9番目...*/ .box:nth-of-type(4n+1) { margin: 0 10px 10px 0; }   /*2,6,10番目...*/ .box:nth-of-type(4n+2) { margin: 0 10px 10px 0; }   /*3,7,11番目...*/ .box:nth-of-type(4n+3) { margin: 0 10px 10px 0; }   /*4,8,12番目...*/ .box:nth-of-type(4n) { margin: 0 0 10px 0; }

まとめるとこんな感じになります。

CSS
.content-body { display: flex;   /*はみ出たら折り返されるようにwrapを設定*/ flex-wrap: wrap;   background-color: #ccc; width: 100%; }   .box { /*ボックス4つの時のの横幅*/ width: calc(100% / 4 - 3 * 10px / 4);   height: 100px; background-color: #999; border: 1px solid #666; }   /*1,5,9番目...*/ .box:nth-of-type(4n+1) { margin: 0 10px 10px 0; }   /*2,6,10番目...*/ .box:nth-of-type(4n+2) { margin: 0 10px 10px 0; }   /*3,7,11番目...*/ .box:nth-of-type(4n+3) { margin: 0 10px 10px 0; }   /*4,8,12番目...*/ .box:nth-of-type(4n) { margin: 0 0 10px 0; }

3つのボックスを均等に配置

同じ方法で3つのボックスを均等配置してみます。

3つのボックスの間に2つの10pxのスペースを空ける式は下になります。

  • width: calc(100% / 3 – 2 * 10px / 3);

3つのボックスの間に2つの10pxのスペースを空ける式は下になります。

  • 一番左側(1,4,7番目…)
    nth-of-type(3n+1)
  • 真ん中(2,5,8番目…)
    nth-of-type(3n+2)
  • 一番右側(3,6,9番目…)
    nth-of-type(3n) {

まとめるとこんな感じになります。

CSS
.content-body { display: flex;   /*はみ出たら折り返されるようにwrapを設定*/ flex-wrap: wrap;   background-color: #ccc; width: 100%; }   .box { /*ボックス3つの時の横幅*/ width: calc(100% / 3 - 2 * 10px / 3);   height: 100px; background-color: #999; border: 1px solid #666; }   /*1,4,7番目...*/ .box:nth-of-type(3n+1) { margin: 0 10px 10px 0; }   /*2,5,8番目...*/ .box:nth-of-type(3n+2) { margin: 0 10px 10px 0; }   /*3,6,9番目...*/ .box:nth-of-type(3n) { margin: 0 0 10px 0; }

ブレイクポイントで4段から3段、2段、1段組みに変化するボックス

今までの方法を活かして、ボックスがブレイクポイントで4段から3段、2段、1段組みに変化するCSSを作ります。それぞれ、横幅が840px以前は4段、840px以下は3段、768px以下は2段、640以下は1段組みになるようにしました。ブレイクポイントの変化を見るにはPCでブラウザの横幅サイズを変更する必要があります。

CSS
.content-body { display: flex; flex-wrap: wrap; background-color: #ccc; width: 100%; }   /*4段組み*/ .box { width: calc(100% / 4 - 3 * 10px / 4); height: 100px; background-color: #999; border: 1px solid #666; }   .box:nth-of-type(4n+1) { /*1,5,9番目...*/ margin: 0 10px 10px 0; }   .box:nth-of-type(4n+2) { /*2,6,10番目...*/ margin: 0 10px 10px 0; }   .box:nth-of-type(4n+3) { /*3,7,11番目...*/ margin: 0 10px 10px 0; }   .box:nth-of-type(4n) { /*4,8,12番目...*/ margin: 0 0 10px 0; }   /*3段組み*/ @media screen and (max-width: 840px) { .box { width: calc(100% / 3 - 2 * 10px / 3); }   .box:nth-of-type(3n+1) { /*1,4,7番目...*/ margin: 0 10px 10px 0; }   .box:nth-of-type(3n+2) { /*2,5,8番目...*/ margin: 0 10px 10px 0; }   .box:nth-of-type(3n) { /*3,6,9番目...*/ margin: 0 0 10px 0; } }   /*2段組み*/ @media screen and (max-width: 768px) { .box.box { width: calc(100% / 2 - 1 * 10px / 2); }   .box:nth-of-type(n) { /*1,3,5番目...*/ margin: 0 10px 10px 0; }   .box.box:nth-of-type(2n) { /*2,4,6番目...*/ margin: 0 0 10px 0; } }   /*1段組み*/ @media screen and (max-width: 640px) { .box { width: 100%; }   .box:nth-of-type(n) { /*すべて*/ margin: 0 0 10px; } }

【方法2】marginのマイナス値を利用する

よく考えたらもっと簡単な方法があった

わざわざボックスの横幅を計算して面倒な方法をとっていたが、よく考えたらもっと簡単な方法があった。

親要素にmarginのマイナス値を利用

marginにはマイナス値も利用できる。なので、親要素を1つ追加し、親要素の左右にボックスのマイナス値のmarginを与えて外側にはみ出した状態にすることで同じ見た目できる。

HTML

先程のHTMLに.content-body-innerを追加します。

<div class="content-body"> <div class="content-body-inner"> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> <div class="box"></div> </div> </div>

以下、CSSです。.content-body-innerの左右をマイナス5pxにし、左右を外側にはみ出します。※背景色は.bodyに設定します。

  • margin:0 -5px(左右5pxはみ出す)

逆に、横幅ははみ出す分、10pxを広く設定します。

  • width: calc(100% + 10px)(横幅を10px追加)
.content-body { /*背景色はbodyに指定*/ background-color: #ccc;   width: 100%; }   .content-body-inner { /*左右5pxはみ出す*/ margin:0 -5px;   /*逆に10pxを広く設定*/ width: calc(100% + 10px);   display: flex; flex-wrap: wrap; }

また、.boxの横幅は先程のはみ出し分の10pxを差し引くだけです。

  • width: calc(100% / 4 – 10px)(ボックスの横幅からスペース分をはみ出し分の10pxを差し引く)
.box { /*はみ出し分の10pxを差し引く*/ width: calc(100% / 4 - 10px);   height: 100px; background-color: #999; border: 1px solid #666; }

まとめるとこんな感じになります。

CSS
.content-body { /*背景色はbodyに指定*/ background-color: #ccc;   width: 100%; }   .content-body-inner { /*左右5pxはみ出す*/ margin:0 -5px;   /*逆に10pxを広く設定*/ width: calc(100% + 10px);   display: flex; flex-wrap: wrap; }     .box { /*はみ出し分の10pxを差し引く*/ width: calc(100% / 4 - 10px);   margin:0 5px 10px; height: 100px; background-color: #999; border: 1px solid #666; }

マイナス値を利用して4段から3段、2段、1段組みに変化する

では上の方法、マイナス値を利用して先程と同じようにボックスがブレイクポイントで4段から3段、2段、1段組みに変化するCSSを作ります。

.content-body { width: 100%; background-color: #ccc; }   .content-body-inner { margin:0 -5px; width: calc(100% + 10px); display: flex; flex-wrap: wrap; }   /*4段組み*/ .box { width: calc(100% / 4 - 10px); margin:0 5px 10px; height: 100px; background-color: #999; border: 1px solid #666; }   /*3段組み*/ @media screen and (max-width: 840px) { .box { width: calc(100% / 3 - 10px); } }   /*2段組み*/ @media screen and (max-width: 768px) { .box { width: calc(100% / 2 - 10px); } }   /*1段組み*/ @media screen and (max-width: 640px) { .box { width: calc(100% - 10px); } }

だいぶCSSの最適化に成功しました!この方法だと、先程のように疑似クラスnth-of-typeを利用しないでも折り返すボックスが作成できます。結果はまったく同じなので、自分の管理しやすい方法でよいと思います。