如何保持包装的flex-items与前一行的元素宽度相同?

mid*_*idu 51 css flexbox

我有一个<ul>flex-box和一堆<li>s里面的flex-items.

我试图让它<li>具有灵活的宽度,使用最小宽度和最大宽度保持两种尺寸.只要它们在同一条线上,它就能很好地工作.但是,当它们换<li>行时,新行上的s会尽可能多地使用空间.这意味着它们在第一行很小,而在第二行很小,只有少数几行.

有没有办法告诉flexbox在包装后保持项目的宽度,同时保持灵活的宽度?

包装演示:

在此输入图像描述

我的代码看起来像这样:

<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>
Run Code Online (Sandbox Code Playgroud)

而CSS:

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

  li {
    min-width: 40px;
    max-width: 100px;
    flex: 1 0 0;
  }
Run Code Online (Sandbox Code Playgroud)

这是一个关于codepen的实例,带有一些额外的注释,调整窗口大小以查看它的包装.

Mer*_*ott 52

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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

将mixin应用于您的flex项:

.flex-item {
  @include flex-wrap-fix(100px)
}
Run Code Online (Sandbox Code Playgroud)

更新:

只要您的Flex容器宽度与视口大小匹配,上面的mixin应该可以解决问题,就像OP的例子中的情况一样.否则,媒体查询将无法帮助您,因为它们始终基于视口宽度.但是,您可以使用css-element-queries库及其元素查询而不是浏览器媒体查询.这是一个可以应用于flex 容器的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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

说明:

让我们说,根据OP的例子,我们希望每个项目的最大宽度为100px,因此我们知道,对于浏览器宽度,100px我们可以在每行中放置一个项目,依此类推:

| 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         |
Run Code Online (Sandbox Code Playgroud)

我们可以编写媒体查询来创建以下规则:

| 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)     |
Run Code Online (Sandbox Code Playgroud)

像这样:

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%; }
}
Run Code Online (Sandbox Code Playgroud)

当然,这是重复的,但很可能你正在使用某种预处理器,它可以为你处理重复性.这正是上面TL中的mixin ; DR部分.

我们现在要做的就是指定100px我们的flex-basis,以及可选的最大浏览器窗口宽度(默认为2000px)来创建媒体查询:

@include flex-wrap-fix(100px)
Run Code Online (Sandbox Code Playgroud)

最后,使用上面的mixin,使用所需输出的原始CodePen示例的分叉版本:

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

演示解决方案


Ome*_*mer 19

替代 - 网格

它不是你想要的答案,但很好用:

display: grid
grid-template-columns: repeat(auto-fill, minmax(70px, 1fr))
Run Code Online (Sandbox Code Playgroud)

https://codepen.io/omergal/pen/povzJrz

display: grid
grid-template-columns: repeat(auto-fill, minmax(70px, 1fr))
Run Code Online (Sandbox Code Playgroud)
ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
}

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

ul,
li {
  margin: 0;
  padding: 0;
  list-style: none;
}
ul {
  background-color: tomato;
}

li {
  margin: 0.5em;
  background-color: darkgreen;
}

img {
  width: 100%;
  opacity: 0.5;
}
figure,
img {
  margin: 0;
  padding: 0;
}
Run Code Online (Sandbox Code Playgroud)

  • MDN 上有一个完整的页面,[Mastering Wrapping of Flex Items](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Mastering_Wrapping_of_Flex_Items#single-Dimension_layout_explained),专门用于 Flex 的包装项目。“Flexbox 中没有方法告诉一行中的项目与上面一行中的项目对齐 - 每条 Flex 行就像一个新的 Flex 容器。...如果您想要二维布局,那么您可能需要网格布局。 ” (2认同)

Pav*_*loz 10

我一直在试验你的codepen,我设置了 flex: 0 1 10%

当然你可以设置任何你想要的弹性基础,我只是想证明一点,如果你设置弹性基础并允许它缩小,在这种情况下它会表现得更好.

我认为这就是你所需要的.这是预览:http: //codepen.io/anon/pen/bwqNEZ

干杯


zer*_*0ne 5

我想我明白了……但这很糟糕。结果是 14 个图像,每个图像的宽度从 100 像素缩放到 40 像素,甚至在多行上也是如此。

宽度从 107 像素到 40 像素

请查看CodePen

和/或全页模式下的片段

li:nth-of-type(n + 15) {
  visibility: hidden;
}
Run Code Online (Sandbox Code Playgroud)
li {
  min-width: 40px;
  max-width: 10%;
  flex: 1 0 100px;
}
Run Code Online (Sandbox Code Playgroud)