web-dev-qa-db-ja.com

ラップされたflex-itemsを前の行の要素と同じ幅に保つ方法は?

フレックスボックスである<ul>とフレックスアイテムである<li>sの束があります。

<li>に柔軟な幅を持たせようとしていますが、これはmin-widthとmax-widthを使用して2つのサイズの間に留まります。それらが同じライン上にある限り、うまく機能します。ただし、折り返すと、新しい行の<li> sはできるだけ多くのスペースを使用します。つまり、最初の行では小さく、2、3の行がある場合は2番目の行で大きくなります。

flexbox柔軟な幅を維持しながら、折り返し後のアイテムの幅を維持するように指示する方法はありますか?

ラッピングデモ:

enter image description here

私のコードは次のようになります。

<ul>
  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/100/100">
    </figure>
  </li>
  <!-- ... -->
</ul>

そしてCSS:

ul {
  display: flex;
  flex-wrap: wrap;
}

  li {
    min-width: 40px;
    max-width: 100px;
    flex: 1 0 0;
  }

追加のコメント付きのコードペンのライブ例、折り返されるようにウィンドウのサイズを変更します。

46
midu

TL; DR

これはsolution自体とは呼ばないものですが、メディアクエリのみを使用する比較的エレガントな回避策であり、さらに重要なのはJavaScriptを使用しないことです

ミックスイン(SCSS):

@mixin flex-wrap-fix($flex-basis, $max-viewport-width: 2000px) {
  flex-grow: 1;
  flex-basis: $flex-basis;
  max-width: 100%;

  $multiplier: 1;
  $current-width: 0px;

  @while $current-width < $max-viewport-width {
    $current-width: $current-width + $flex-basis;
    $multiplier: $multiplier + 1;

    @media(min-width: $flex-basis * $multiplier) {
      max-width: percentage(1/$multiplier);
    }
  }
}

使用法:

フレックスアイテムにミックスインを適用します。

.flex-item {
  @include flex-wrap-fix(100px)
}

更新:

OPの例の場合のように、フレックスコンテナの幅がビューポートのサイズと一致している限り、上記のmixinはトリックを行う必要があります。メディアクエリは、ビューポートの幅に常に基づいているため、そうしないと役に立ちません。ただし、ブラウザメディアクエリの代わりに css-element-queries ライブラリとその要素クエリを使用できます。 flexcontainerに適用できるmixinは次のとおりです。

@mixin flex-container-wrap-items($flex-basis, $max-expected-width: 2000px) {
  display: flex;
  flex-wrap: wrap;

  > * {
    max-width: 100%;
    flex-grow: 1;
    flex-basis: $flex-basis;
  }

  $multiplier: 1;
  $current-width: 0px;

  @while $current-width < $max-expected-width {
    $current-width: $current-width + $flex-basis;
    $multiplier: $multiplier + 1;

    &[min-width~="#{$flex-basis * $multiplier}"] > * {
      max-width: percentage(1/$multiplier);
    }
  }
}

説明:

OPの例に従って、各アイテムに100pxの最大幅を持たせたいので、ブラウザの幅が100pxの場合、行ごとに1つのアイテムを収めることができることを知っています。 :

| Viewport Width | Max Item Count Per Row | Item Width (min-max) |
|----------------|------------------------|----------------------|
| <= 100         | 1                      | 0px - 100px          |
| <= 200         | 2                      | 50px - 100px         |
| <= 300         | 3                      | 50px - 100px         |
| <= 400         | 4                      | 50px - 100px         |
| <= 500         | 5                      | 50px - 100px         |
| <= 600         | 6                      | 50px - 100px         |

メディアクエリを記述して、次のルールを作成できます。

| Viewport Width | Max Item Count Per Row | Item Max Width | Calculation |
|------------------------------------------------------------------------|
| <= 100px       | 1                      | 100%           | (100/1)     |
| <= 200px       | 2                      | 50%            | (100/2)     |
| <= 300px       | 3                      | 33.33333%      | (100/3)     |
| <= 400px       | 4                      | 25%            | (100/4)     |
| <= 500px       | 5                      | 20%            | (100/5)     |
| <= 600px       | 6                      | 16.66666%      | (100/6)     |

このような:

li {
  flex: 1 0 0
  max-width: 100%;
}

@media(min-width: 200px) {
  li { max-width: 50%; }
}

@media(min-width: 300px) {
  li { max-width: 33.33333%; }
}

@media(min-width: 400px) {
  li { max-width: 25%; }
}

@media(min-width: 500px) {
  li { max-width: 20%; }
}

@media(min-width: 600px) {
  li { max-width: 16.66666%; }
}

もちろん、それは反復的ですが、ほとんどの場合、何らかのプリプロセッサを使用しているので、反復性の面倒を見ることができます。それがまさに上記のTL; DRセクションのmixinが行うことです。

あとは、100pxflex-basisとして指定し、オプションでブラウザーウィンドウの最大幅(デフォルトは2000px)を指定するだけです次のメディアクエリを作成します。

@include flex-wrap-fix(100px)

最後に、上記のmixinを使用して、目的の出力を持つ元のCodePenサンプルの分岐バージョン:

http://codepen.io/anon/pen/aNVzoJ

demo of the solution

51
Merott

私はあなたのコードペンで実験しており、flex: 0 1 10%

もちろん、フレックスベーシスは任意に設定できますが、ポイントを証明したかったのです。フレックスベーシスを設定して縮小できるようにすると、この場合はずっとうまく動作します。

これがあなたが必要とするものだと思います。プレビューは次のとおりです。 http://codepen.io/anon/pen/bwqNEZ

乾杯

9
Pavelloz

私はそれを得たと思う...しかしそれはハッキーだ。その結果、複数の行であっても、それぞれ幅100ピクセルから40ピクセルまでスケーリングする14個の画像が得られます。

From 107px to 40px Width

  • 14個の元の<li>sの複製セットを追加し、フレックス<ul>に追加しました。
  • 次に、2番目のセットが非表示になりました。

    li:nth-of-type(n + 15) {
      visibility: hidden;
    }
    
  • 均一な柔軟性を維持するために、各<li>に次の変更を加えます。

    li {
      min-width: 40px;
      max-width: 10%;
      flex: 1 0 100px;
    }
    

確認してくださいCodePen

および/またはSnippetFull Pageモードで。

ul {
  display: flex;
  flex-wrap: wrap;
  max-height: 258px;
}
li {
  min-width: 40px;
  max-width: 10%;
  flex: 1 0 100px;
}
ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}
ul {
  background-color: tomato;
}
li {
  margin: 0.5em;
  background-color: darkgreen;
}
li img {
  width: 100%;
  opacity: 0.5;
}
li figure,
li img {
  margin: 0;
  padding: 0;
}
li:nth-of-type(n + 15) {
  visibility: hidden;
}
<ul>
  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/101/101">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/201/201">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/80/80">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/111/111">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/40/40">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/110/110">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/75/75">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/89/89">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/32/32">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/61/61">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/320/320">
    </figure>
  </li>



  <li>
    <figure>
      <img src="http://placekitten.com/g/250/250">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/101/101">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/201/201">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/80/80">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/111/111">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/40/40">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/110/110">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/75/75">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/89/89">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/150/150">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/32/32">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/61/61">
    </figure>
  </li>
  <li>
    <figure>
      <img src="http://placekitten.com/g/320/320">
    </figure>
  </li>
</ul>
3
zer00ne

私が持っているフレックスボックスの同じ問題を解決するためにここに来ました。それ以来、これはdisplay: grid as detail here および here

2
jdnz

min-widthおよびmax-widthパーセンテージとして、すべての画像が次の行に分割されたときに同じ幅を維持できるようにしました。それは理想的ではありませんが、あなたが望んでいるものに近いですか?

li {
  min-width: 15%;
  max-width: 15%;  
}
2
lili2311

うまく機能しませんが、列を使用してこの方向で何かを達成できます。

column-gap: 10px;
column-width: 150px;

https://codepen.io/hobbeshunter/pen/OgByNX

1
hobbeshunter

スタイラスでは、このミックスインを使用できます: https://codepen.io/anon/pen/Epjwjq


   flex-wrap-fix($basis, $max) {
     flex-grow: 1
     flex-basis: $basis
     max-width: 100%

     $multiplier = ceil($max / $basis)

     for i in (1..$multiplier) {
       @media(min-width: ($basis * i)) {
         max-width: percentage(1/i)
       }
     }
   }
0
Daniel D

私のソリューションは、JQueryに依存しているため、理想的ではありません。 http://codepen.io/BigWillie/pen/WwyEXX

CSS

ul {
  display: flex;
  flex-wrap: wrap;
}

li {
  min-width: 40px;
  max-width: 100px;
  flex: 1;
}

JavaScript

var eqRowFlexItem = function(elem) {
    var w;
    var $elem = $(elem);
    // Clear out max-width on elements
    $elem.css('max-width', '');
    w = $(elem).eq(0).width();
    $(elem).css('max-width', w);
}

eqRowFlexItem('li');

$(window).resize(function() {
    eqRowFlexItem('li');
});

それが問題に答えているかどうかは完全にはわかりません。タイトルが私が抱えていた問題と一致していたので、私はこの投稿を見つけました。大きな画面では行ごとの要素数が多くなり、小さな画面では行ごとの要素数が少なくなるという効果がありました。どちらの場合も、これらの要素はデバイスに合わせて拡張する必要がありました。

ただし、最後の行のこれらの浮遊要素は、常に残りのスペースを埋めるように拡大します。

JQueryは最初の要素の幅を取得し、すべての要素に最大幅として適用します。 OPは、ブロックを最小幅/最大幅の範囲内に収めることを望んでいました。 CSSでmax-widthを設定するとうまくいくようです。要素のmax-widthをクリアするため、CSSのmax-widthがデフォルトになり、実際の幅が取得されます。

0
Rob

私は同じ問題を抱えていたので、非常に小さなJqueryを使用してボックスの幅を制御し、折り返した後でもすべて同じ幅にしました。

私のデモはCodePenにあります フレックスラップ、新しい行に等しい幅で

function resize(){
  var colWidth;
  var screen = $(window).width(); 
  
  if(screen < 576){
    colWidth = Math.round(screen / 2) - 31;
    $(".item").width(colWidth);
  } 
  if(screen > 575 && screen < 768){
    colWidth = Math.round(screen / 3) - 31;
    $(".item").width(colWidth);
  } 
  else if (screen > 767 && screen < 992){
      colWidth = Math.round(screen / 4) -31;
      $(".item").width(colWidth);
  }
  else if (screen > 991 ){
      colWidth = Math.round(screen / 6) -31;
      $(".item").width(colWidth);
  }
}
  
window.onresize = function() {
  resize();
}

resize();
html,
body{
  padding:0;
  margin:0;
}
.flex-container {
  padding: 0;
  margin: 0;
  list-style: none;
  -ms-box-orient: horizontal;
  display: -webkit-box;
  display: -moz-box;
  display: -ms-flexbox;
  display: -moz-flex;
  display: -webkit-flex;
  display: flex;
  justify-content: left;
  background-color:#ddd;
}

.wrap    { 
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
}  

.item {
  background: tomato;
  height: 100px;
  margin:0 15px;
  line-height: 100px;
  color: white;
  font-weight: bold;
  font-size: 2em;
  text-align: center;
  margin-top:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="flex-container wrap">
  <li class="item">1</li>
  <li class="item">2</li>
  <li class="item">3</li>
  <li class="item">4</li>
  <li class="item">5</li>
  <li class="item">6</li>
  <li class="item">7</li>
  <li class="item">8</li>
  <li class="item">9</li>
</ul>
0
T.Hallam

これは完璧ではありませんが、試してみる価値があります。 http://codepen.io/anon/pen/MKmXpV

変更点は

li
  width: 7.1428%
  flex: 0 0 auto

figure
  margin: 0 auto
  background-color: darkgreen
  min-width: 40px
  max-width: 100px
  • li flexを「0 0 auto」に変更し、li幅をlisの数に基づいたパーセンテージに変更しました。
  • 最小幅と最大幅をliから図に移動しました
  • 緑の背景を図に移動し、図の中心をlisに合わせました
0
Miriam Salzer