web-dev-qa-db-ja.com

フレックスボックス:最後の行をグリッドに合わせる

次のようなコンテナを使った簡単なフレックスボックスのレイアウトがあります。

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

最後の行の項目を他の項目と整列させます。グリッドの幅と高さを調整できるため、justify-content: space-between;を使用する必要があります。

現在はこんな感じです

The item in the bottom right should be in the middle

ここでは、右下の項目を「中央の列」に入れます。それを達成するための最も簡単な方法は何ですか?これがこの振る舞いを示す小さな jsfiddle です。

.exposegrid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.exposetab {
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>
300

スペースを自動入力する ::after を追加します。 HTMLを汚染する必要はありません。これはそれを示すcodepenです: http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid::after {
  content: "";
  flex: auto;
}
338
Dan Andreasson

1つの方法は、高さがゼロになるようにいくつかの余分な要素を挿入することです(1行に含まれると予想される要素の最大数まで)。スペースはまだ分割されていますが、余分な行は何もしなくなります。

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

将来的には、これは複数の ::after(n) を使用することで実現可能になるかもしれません。

143
dalgard

他のポスターが述べているように - 最後の行をflexboxで左寄せするきれいな方法はありません(少なくとも現在の仕様による)

しかし、その価値はなんでしょうか: CSSグリッドレイアウトモジュール を使えば、これは驚くほど簡単に作成できます。

基本的には、関連するコードは次のようになります。

ul {
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */
}

1)コンテナ要素をグリッドコンテナにする

2)幅100ピクセルのオートコラムでグリッドを設定します。 ( auto-fillauto-fitと同じように - これは(1行レイアウトの場合)0に空のトラックを折りたたみます) - 項目が残りの部分を占めるように拡張する原因になります。これは、gridに1行しかない場合には「スペース間」のレイアウトが正当化されることを意味しますが、これは私たちの目的ではありません(違いを確認するには this demo をご覧くださいそれらの間の))。

3)グリッドの行と列にギャップ/ガターを設定します - ここでは、 'スペース間'レイアウトが必要なため、ギャップは必要に応じて拡大するため、実際には最小ギャップになります。

4)flexboxに似ています。

ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  grid-gap: 1rem;
  justify-content: space-between;
  
  /* boring properties */
  list-style: none;
  background: wheat;
  padding: 2rem;
  width: 80vw;
  margin: 0 auto;
}

li {
  height: 50px;
  border: 1px solid green;
}
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Codepen Demo (サイズを変更して効果を確認します)

65
Danield

余分なマークアップがなくても、::afterを追加するだけで列の幅を指定できました。

.grid {
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
}
.grid::after{
  content: '';
  width: 10em // Same width of .grid__element
}
.grid__element{
  width:10em;
}

このようなHTMLでは:

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>
21

できません。 Flexboxはグリッドシステムではありません。少なくともjustify-content: space-betweenを使っているのでなければ、それはあなたが求めていることをするための言語構成要素を持っていません。 Flexboxで一番近いのは列の向きを使うことです。これには明示的な高さを設定する必要があります。

http://cssdeck.com/labs/pvsn6t4z (注:プレフィックスは含まれません)

ul {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;
}

ただし、列を使用するほうが簡単です。これにより、サポートが向上し、特定の高さを設定する必要がなくなります。

http://cssdeck.com/labs/dwq3x6vr (注:プレフィックスは含まれません)

ul {
  columns: 15em;
}
13
cimmanon

考えられる解決策は、justify-content: flex-start;コンテナーに.gridを使用し、その子にサイズ制限を設定し、適切な子要素に余白を設定することです(必要な列数に応じて)。

3列グリッドの場合、基本的なCSSは次のようになります。

.grid {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}

.grid > * {
    flex: 0 0 32%;
    margin: 1% 0;
}

.grid > :nth-child(3n-1) {
    margin-left: 2%;
    margin-right: 2%;
}

それはもう一つの不完全な解決策ですが、うまくいきます。

http://codepen.io/tuxsudo/pen/VYERQJ

8
Jared

アイテムとアイテムの間にスペースを空けずにグリッドを作成したい場合は、この簡単な方法でうまくいきます。

.grid {
    display: flex;
    flex-flow: row wrap;
    margin: 0 -5px; // remove the inital 5px space
    width: auto;
}
.grid__item {
    width: 25%;
    padding: 0 5px; // should be same as the negative margin above.
}

あなたが最初の5pxスペースが欲しいならば、ちょうど負のマージンを取り除いてください:)シンプル。

https://jsfiddle.net/b97ewrno/2/

受け入れられた答えですが、それでも、2行目の要素間にスペースが入りません。

5
OZZIE

最後のアイテムをグリッドに揃えたい場合は、次のコードを使用します。

グリッドコンテナ

.card-grid {
  box-sizing: border-box;
  max-height: 100%;
  display: flex;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  justify-content: space-between;
  align-items: stretch;
  align-content: stretch;
  -webkit-box-align: stretch;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;
}

.card-grid:after {
  content: "";
  flex: 1 1 100%;
  max-width: 32%;
}

グリッド内の項目

.card {
  flex: 1 1 100%;
  box-sizing: border-box;
  -webkit-box-flex: 1;
  max-width: 32%;
  display: block;
  position: relative;

}

コツは、項目の最大幅を.card-grid:afterの最大幅に等しく設定することです。

Codepenのライブデモ

4
Frank Spin

はい。!しかし、いくつかのメディアクエリでは、&列の最大数は事前定義されています

ここでは4列を使っています。私のコードをチェックしてください。

.container {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -moz-flex-flow: row wrap;
}

.container .item {
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  justify-content: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
}

.container .item .item-child {
  width: 130px;
  height: 180px;
  background: red;
  margin: 10px;
}

@media (max-width: 360px) {
  .container .item {
    flex-basis: 100%;
  }
}

@media (min-width:360px) and (max-width: 520px) {
  .container .item {
    flex-basis: 50%;
  }
}

@media (min-width:520px) and (max-width: 680px) {
  .container .item {
    flex-basis: 33.33%;
  }
}
<div class="container">

  <div class="item">
    <div class="item-child">1</div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>

</div>

NOTE
1)子divを作成する必要はありません。それはあなたが望むものなら何でも 'img' rのような他のタグかもしれません..
2)さらに多くの列が必要な場合は、メディアクエリと最大列数を調整します。

"flex-start"を使用して余白を手動で追加することは可能です。それはいくつかの数学的なハッキングを必要としますが、確かにするのが簡単で、LESSのようなCSSプリプロセッサでそれを使うのを簡単にします。

例えば、このLESS mixinを見てください。

.flexboxGridMixin(@columnNumber,@spacingPercent) {
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * {
    box-sizing: border-box;
    width: @contentPercent/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  }
}

それから、レスポンシブグリッドレイアウトを表示するために簡単に使用できます。

ul {
  list-style: none;
  padding: 0;
  @spacing: 10%;
  @media only screen and (max-width: 499px) { .flexboxGridMixin(1,@spacing); }
  @media only screen and (min-width: 500px) { .flexboxGridMixin(2,@spacing); }
  @media only screen and (min-width: 700px) { .flexboxGridMixin(3,@spacing); }
  @media only screen and (min-width: 900px) { .flexboxGridMixin(4,@spacing); }
  @media only screen and (min-width: 1100px) { .flexboxGridMixin(5,@spacing); }
}

li {
  background: pink;
  height: 100px;
  margin-top: 20px;
}

これはの例です

http://codepen.io/anon/pen/YyLqVB?editors=110

3

ここには多くの答えがありますが、..これを行う最も簡単な方法は、gridgrid template columnsflexauto fillsでなく、repeatを使用することです。各要素にスニペットコードから100px与えたピクセル数を設定する必要があります。

.exposegrid {
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;
}
 .exposetab {
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
}
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>
3
SilverSurfer

このバージョンは、固定幅のブロックに最適な方法です。

http://codepen.io/7iomka/pen/oxxeNE

その他の場合 - dalgardのバージョン

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
justify-content:center;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  max-width:200px;
  min-width:200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>
0

行内の要素間のスペースの幅と行内の要素の量がわかっていれば、これは機能します。

例:1行に3つの要素、要素間に10ピクセルの間隔

div:last-child:nth-child(3n+2) {
  flex-grow: 1
  margin-left: 10px
}
0
norweny

次の条件を満たす必要がありますが、flexboxを使用しない方法もあります。 1)コンテナにパディングがあります。 2)商品は同じサイズで、1行に何個必要かを正確に知っています。

ul {
  padding: 0 3% 0 5%;
}
li {
  display: inline-block; 
  padding: 0 2% 2% 0;
  width: 28.66%;
}

コンテナの右側にある小さなパディングは、各リスト項目の右側に追加のパディングを可能にします。リストオブジェクトと同じ親の他の項目が0 5%で埋め込まれると仮定すると、それはそれらと同じ高さになります。パーセンテージを調整して好みの余裕を持たせることも、px値を計算することもできます。

もちろん、n番目の子(IE 9以降)を使用して3番目のボックスごとに余白を削除することで、コンテナの余白なしで同じことを実行できます。

0
ansorensen

これは多くの答えの組み合わせですが、それは私が必要としていたこととまったく同じです。つまり、フレックスコンテナ内の最後の子を左に揃えながら、スペース間の動作を維持します。レイアウト)。

これがマークアップです。

.flex-container {
  display: flex;
  justify-content: space-between;
  flex-direction: row;
}

.flex-container:after {
  content: "";
  flex-basis: 30%;
}
0
Margaret

あなたはflex-startとmax-widthで簡単にこれを達成することができます。

https://codepen.io/moladukes/pen/NvzBrQ

.container {
  display: flex;
  justify-content: flex-start;
  flex-flow: row wrap;
}

.item { 
  width: 130px; 
  max-width: 130px; 
  height: 180px; 
  background: red; 
  margin: 20px; 
}
0
moladukes

Flexboxといくつかのメディアクエリを使用して、私はこの小さな回避策を作りました: http://codepen.io/una/pen/yNEGjv (そのちょっとハッキーだけどうまくいく):

.container {
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  max-width: 1200px;
  margin: 0 auto;
}

.item {
  background-color: gray;
  height: 300px;
  flex: 0 30%;
  margin: 10px;

  @media (max-width: 700px) {
     flex: 0 45%;
  }

  @media (max-width: 420px) {
    flex: 0 100%;
  }

  &:nth-child(3n-1) {
    margin-left: 10px;
    margin-right: 10px;
  }
}
0
Una Kravets

これはかなりハッキーですが、私にとってはうまくいきます。私は一貫した間隔/マージンを達成しようとしていました。

.grid {
  width: 1024px;
  display: flex;
  flex-flow: row wrap;
  padding: 32px;
  background-color: #ddd;  

  &:after {
    content: "";
    flex: auto;
    margin-left:-1%;
  }

  .item {
    flex: 1 0 24.25%;
    max-width: 24.25%;
    margin-bottom: 10px;
    text-align: center;
    background-color: #bbb;

    &:nth-child(4n+2),
    &:nth-child(4n+3),
    &:nth-child(4n+4) {
      margin-left: 1%;
    }

    &:nth-child(4n+1):nth-last-child(-n+4),
      &:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
        margin-bottom: 0;
    }    

  }
}

http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/

0
RustyDev

これがもう一つのscss mixinです。

これらのミックスインは、あなたがIsotopeのようなjsプラグインを使うつもりはないと仮定しています(それらはhtmlマークアップ順を尊重しないので、css nthルールでめちゃくちゃにします)。

また、あなたがレスポンシブブレークポイントをモバイルファーストの方法で書いている場合は特に、それらを最大限に活用することができるでしょう。理想的には、小さいブレークポイントではflexbox_grid()を使用し、次のブレークポイントではflexbox_cell()を使用します。 flexbox_cell()は、以前に設定されたマージンを大きなブレークポイントで使用しないようにリセットします。

ところで、コンテナのflexプロパティを正しく設定している限り、必要に応じて項目にflexbox_cell()だけを使用することもできます。

これがコードです:

// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $Gutter_width){

  display: flex;
  flex-direction:row;
  flex-wrap:wrap;
  justify-content: flex-start;

  > *{
    @include flexbox_cell($columns, $Gutter_width);
  }
}

// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $Gutter_width){
  $base_width: 100 / $columns;
  $gutters: $columns - 1;
  $Gutter_offset: $Gutter_width * $gutters / $columns;

  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto; // IE10 doesn't support calc() here

  box-sizing:border-box; // so you can freely apply borders/paddings to items
  width: calc( #{$base_width}% - #{$Gutter_offset} );

  // remove useless margins (for cascading breakponts)
  &:nth-child(#{$columns}n){
    margin-right: 0;
  }

  // apply margin
  @for $i from 0 through ($gutters){
    @if($i != 0){
      &:nth-child(#{$columns}n+#{$i}){
        margin-right: $Gutter_width;
      }
    }
  }
}

使用法:

ul{
   // just this:
   @include flexbox_grid(3,20px);
}

// and maybe in following breakpoints, 
// where the container is already setted up, 
// just change only the cells:

li{
   @include flexbox_cell(4,40px);
}

明らかに、コンテナの余白/余白/幅とセルの余白などを最終的に設定するのはあなた次第です。

それが役に立てば幸い!

0
Luca Reghellin

と仮定します。

  • 折り返し付き4列グリッドレイアウトが必要です
  • 項目の数は必ずしも4の倍数ではありません

1、5、9番目の項目を除くすべての項目に左マージンを設定します。左マージンが10ピクセルの場合、各行には4アイテム間に30ピクセルのマージンがあります。 itemのパーセント幅は次のように計算されます。

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

これは、flexboxの最後の行に関する問題に対する適切な回避策です。

.flex {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0 3em;
  background-color: peachpuff;
}

.item {
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;
}

.item:nth-child(4n + 1) {
  margin-left: 0;
}

.item:nth-child(n + 5) {
  margin-top: 10px;
}
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
</div>
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
  <div class="item">9</div>
</div>
0
Salman A

最後の項目については、誰もがFlex-Growソリューションを提案していないようです。これは、flex-growを使用して、最後のフレックスアイテムにすべての場所を取り入れるという考え方です。

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid > *:last-child {
  flex-grow: 1;
}

注:このソリューションは、特にフレックスアイテムの内側に要素を配置している場合は、最後のフレックスアイテムを中心に配置するため、完璧ではありません。

0
Dionys

私はそれのためにSCSSミックスインを作りました。

@mixin last-row-flexbox($num-columns, $width-items){

  $filled-space: $width-items * $num-columns;
  $margin: calc((100% - #{$filled-space}) / (#{$num-columns} - 1));

  $num-cols-1 : $num-columns - 1;

  &:nth-child(#{$num-columns}n+1):nth-last-child(-n+#{$num-cols-1}) ~ & {
    margin-left: $margin;
  }
  @for $i from 1 through $num-columns - 2 { 
    $index: $num-columns - $i;
    &:nth-child(#{$num-columns}n+#{$index}):last-child{
      margin-right: auto;
    }
  }
}

これはcodepenのリンクです: http://codepen.io/diana_aceves/pen/KVGNZg

アイテムの幅をパーセンテージと列数で設定するだけです。

これがお役に立てば幸いです。

0
Diana