1. ホーム
  2. css

ラップされたフレックスアイテムを前の行の要素と同じ幅に保つには?

2023-10-31 12:33:42

質問

私は <ul> があり、その中にフレックスボックスである <li> があり、その中にフレックスアイテムがあります。

を取得しようとしているのですが <li> を、min-width と max-width を使って2つのサイズの間に留まる柔軟な幅を持つようにしようとしています。同じ行にある限りはうまくいきます。しかし、それらがラップされると <li> はできる限りのスペースを使用します。つまり、1行目では小さく、2行目では大きいということです。

フレキシブルな幅を維持したまま、折り返し後の幅を維持するように flexbox に指示する方法はありますか?

wrapping demo:

私のコードはこんな感じです。

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

これは、codepen上のライブの例で、いくつかの追加コメントがあります。 ウィンドウをリサイズしてご覧ください。

どのように解決するのですか?

TL;DR

これは、私が ソリューション とは呼べませんが、メディアクエリのみを使用した、かなりエレガントな回避策です。 JavaScript を使用しない !

Mixin (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の例のようにフレックスコンテナの幅がビューポートサイズと一致している限り、トリックを行うことができます。メディアクエリは常にビューポートの幅に基づいているため、そうでない場合は役に立ちません。しかし css-element-queries ライブラリとその要素クエリを、ブラウザのメディアクエリの代わりに使用することができます。以下に、フレックスに適用できるミキシンを示します。 コンテナ :

@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つの行に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 がそうです。

あとは 100px を指定することです。 flex-basis であり はオプションで ブラウザのウィンドウ幅の最大値(デフォルトは 2000px ) のためにメディアクエリを作成します。

@include flex-wrap-fix(100px)

最後に、上記のミキシンを使って、オリジナルのCodePenの例をフォークしたものを、希望通りの出力にしたものを示します。

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