CSS:flex-wrap 创建一个大空间,该空间随着添加到其中网格的元素数量而增长

run*_*ace 6 css

在下面的示例中,有一个很大的红色间隙,我认为不应该存在,这里称为“间隙”。它出现在 Firefox 和 Chrome 中。所以我想纠正一下我对flex/grid容器的理解。

奇怪的是,这个空间的增长取决于放置的物品数量#CONTAINER。如果您将其中的项目数量减半,例如 4(111 到 444),那么空间将减半,如果您向其中添加项目,空间将会增加。

我只是不明白这个差距从何而来,为什么差距会越来越大又越来越小。我通过反复试验确定它会在flex-wrap: wrap应用时发生。#CARD所以这篇文章不是关于“修复下面的代码,使其以某种方式运行”。这是关于了解空间从哪里来?为什么添加物品#CONTAINER后空间会变大?

注意:我需要flex-wrap: wrap在我的真实代码中,这只是一个最小的可重现示例。

#CARD {
  background: lightgray;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  padding: 8px;
}

#SECTION {
  background: red;
  display: flex;
  flex-direction: column;
}

#CONTAINER {
  background: green;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 268px), 1fr));
}
Run Code Online (Sandbox Code Playgroud)
<div id="CARD"><!-- gray -->
  <div id="SECTION"><!-- red -->
    <div id="CONTAINER"><!-- green -->
      <div>
        <div>111</div>
        <div>222</div>
      </div>
      <div>
        <div>333</div>
        <div>444</div>
      </div>
      <div>
        <div>555</div>
        <div>666</div>
      </div>
      <div>
        <div>777</div>
        <div>888</div>
      </div>
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

Dar*_*kes 2

在本例中,flex 容器的高度取决于其内容,即网格容器的高度。然而,网格容器的高度将根据其布局的宽度而变化,在这种情况下,它的变化取决于它是单行还是多行弹性容器。

\n

对于单行弹性容器,网格容器的宽度被认为是“确定的”,并且其高度是通过使用该宽度进行布局来计算的。

\n

对于多行 Flex 容器,网格容器的宽度是不确定的,因此高度是通过布局来计算的,就好像它已width: fit-content应用一样。

\n

然后将计算出的高度用作弹性容器的高度。

\n

因此,网格将始终是 Flex 容器的内部交叉尺寸的宽度,即 Flex 容器的包含块的宽度减去边距、边框和填充。但是,由于单行和多行柔性容器之间的确定尺寸不同,因此高度取决于它是单行还是多行容器!

\n

任何较低的子级(包括网格容器,如果它和包装弹性容器之间有元素)通常都会在此子级中布局。

\n

width: fit-content对网格容器的影响总结:

\n

使用andwidth: fit-content时,每一行将仅包含一个项目,因此每个项目将占一行,这意味着在这种情况下的总高度只是网格中项目高度的总和。这就是导致总高度(网格+间隙)根据其中的项目数量线性调整大小的原因。auto-fillauto-fit

\n

如果没有auto-fillauto-fit,网格将具有不同的行为,这不会导致弹性盒中出现此行为。请参阅我的CodePen 演示的不同组合(默认宽度 + auto-fill、默认宽度 + 固定列数、fit-content+ auto-fillfit-content+ 固定列数)。

\n
\n

基于正常的网格行为,直观的期望是不应该有间隙,并且,在不启用环绕的情况下,它确实按预期运行。然而,使用换行时所涉及的布局计算差异则不然。

\n
    \n
  1. 仅在外部 Flex 容器上启用换行会导致您所描述的行为。
  2. \n
  3. 仅在内部弹性容器上启用换行会导致类似的行为:卡片最终具有相同的高度,但网格填充内部弹性容器。
  4. \n
  5. 仅使用网格周围的包裹 Flex 容器会导致网格具有相同的“最大高度”,如 2 中所示。
  6. \n
\n

在您的情况(1)中,我们有一个网格容器,位于单行柔性容器内,位于多行柔性容器内。

\n

如图 3 所示,即使只有一个 Flex 容器,该行为也会显现出来。一个用于探索的简化案例!

\n

注意:
\n网格行因为是隐式的,所以共享可用的垂直空间。
\n这意味着,虽然父级仍然高于正常情况,但如果网格由于宽度不足而形成多行,则不会具有多个元素的情况那样明显。
\n但是,它仍然是相同的核心行为。

\n

所以“问题陈述”:
\n由于某种原因,弹性容器的高度被计算为网格的高度,每个项目都在其自己的行上,并保持在该高度。

\n

CodePen 重现可跟随或只是摆弄。

\n
\n

进入规格之地!

\n

以供参考:

\n

“确定尺寸”定义如下:

\n
\n

无需进行布局即可确定的尺寸;也就是说, a <length>,文本的度量(不考虑换行),初始包含块的大小,或 a 或其他公式(例如 \xe2\x80\x9cstretch-fit\xe2\x80\x9d 的大小调整)非替换块 [CSS2])仅根据确定的大小进行解析。

\n

此外,绝对定位元素的包含块的大小始终相对于该元素是确定的。

\n
\n

“弹力合身”尺码部分是这里的关键;这就是导致块级元素拉伸到其包含块的宽度的原因。由于初始包含块的大小是确定的,并且这种“拉伸配合”是根据 Flex 容器的初始包含块解析的(显然,它通过多层嵌套递归地工作),因此Flex 容器具有确定的宽度

\n

Flex 容器的“主尺寸”是沿其主轴线的尺寸,“主尺寸属性”是控制它的属性(widthheight)。由于在本例中容器使用的是柱,因此主要尺寸是高度。
\n十字尺寸是另一个尺寸。在这种情况下,宽度。

\n

Flex布局算法定义了一些额外的情况:

\n
\n

9.8. 确定尺寸和不定尺寸

\n

尽管 CSS Sizing [CSS-SIZING-3] 定义了确定长度和不确定长度,但 Flexbox 还有几种其他情况,其中长度可以被视为确定长度:

\n
    \n
  1. 如果弹性容器具有确定的主尺寸,则其弹性项目的弯曲后主尺寸将被视为确定的。

    \n
  2. \n
  3. 如果一个弹性项目\xe2\x80\x99的弹性基础是确定的,那么它的弹性后主要尺寸也是确定的。

    \n
  4. \n
  5. 如果单行 Flex 容器具有明确的交叉尺寸,则任何拉伸 Flex 项目的自动首选外部交叉尺寸为 Flex 容器\xe2\x80\x99s 内部交叉尺寸(夹紧到 Flex 项目\xe2\x80\x99s 最小)和最大交叉尺寸)并且被认为是确定的。

    \n
  6. \n
  7. 一旦确定了柔性线的交叉尺寸,出于布局的目的,自动调整大小的柔性容器中的项目的交叉尺寸也被认为是确定的;请参阅步骤 11。

    \n
  8. \n
\n
\n

第 3 点对我们来说很重要。

\n

现在,深入了解Flex 布局算法......

\n
\n

9.2. 线长测定

\n

最终结果是弹性容器的主要尺寸(在本例中为高度),即线条的长度。

\n
\n
    \n
  1. 确定弹性项目的可用主空间和交叉空间。对于每个维度,如果 flex 容器\xe2\x80\x99s 内容框的该维度是确定的大小,则使用它;
  2. \n
\n
\n

是的,Flex容器的横向尺寸(宽度)是确定的,并且是包含块的宽度。

\n

主要尺寸(高度)是无限的,因此是不确定的。

\n
\n

如果弹性容器的该尺寸在最小或最大内容约束下调整大小,则该尺寸中的可用空间就是该约束;

\n
\n

不,这些限制都不是。

\n
\n

否则,从该维度中 Flex 容器的可用空间中减去 Flex 容器\xe2\x80\x99s 的边距、边框和填充,并使用该值。这可能会产生无穷大的值。

\n
\n

主要维度是垂直的,这为我们在该方向上提供了无限的可用空间。

\n
\n
    \n
  1. 确定每个项目的弹性基础尺寸和假设的主要尺寸:
  2. \n
\n
\n
\n

A. 如果该项目具有明确的使用的 Flex 基础,则\xe2\x80\x99 是 Fl​​ex 基础尺寸。

\n
\n

flex 基础默认为auto,它“检索主尺寸属性的值作为使用的flex-basis”。
\n“如果该值是它本身auto,则使用的值为content”,它“表示基于 Flex item\xe2\x80\x99s 内容的自动大小。”

\n

所以,不,不存在“明确使用的柔性基础”,因为它取决于内容,这将需要执行布局。

\n

“B”点不适用(这些项目没有首选的纵横比)。

\n

点“C”不适用(Flex 容器的大小未在最小内容或最大内容约束下调整)。

\n

点“D”不适用(flex item\xe2\x80\x99s 内联轴不平行于主轴)。

\n

所以,“E”:

\n
\n

E. 否则,使用其使用的 Flex 基础代替其主要大小,将项目调整到可用空间中,将值content视为max-content。如果需要交叉尺寸来确定主尺寸(例如,当flex item\xe2\x80\x99s的主尺寸位于其块轴上时,或者当它具有首选宽高比时)和flex item\xe2\x80\x99s交叉尺寸是auto不确定的,在此计算中使用fit-content作为弹性项目\xe2\x80\x99s的交叉尺寸。Flex 基本尺寸是 item\xe2\x80\x99s 生成的主要尺寸。

\n
\n

这就是问题的核心!

\n

从之前关于确定尺寸的注释来看:

\n
\n

如果单行 Flex 容器具有明确的交叉尺寸,则任何拉伸 Flex 项目的自动首选外部交叉尺寸为 Flex 容器\xe2\x80\x99s 内部交叉尺寸(夹紧到 Flex 项目\xe2\x80\x99s 最小)和最大交叉尺寸)并且被认为是确定的。

\n
\n

柔性容器的横截面尺寸是确定的,是的。因此,如果它是单行Flex容器(未启用换行),则项目的外部交叉尺寸(宽度)就是 Flex 容器的宽度,并且是确定的!\n因此,对于单行 Flex 容器,网格的主要大小(其高度)就是正常布局下的大小,具有自动宽度

\n

如果它是多行容器,则它用作fit-content交叉尺寸(宽度):
\n网格容器的主要尺寸位于其块轴上,其交叉尺寸(宽度)是auto不确定的(因为它是一个多行柔性容器)。因此,fit-content在计算其高度时,将其用作网格容器的宽度。

\n

fit-content是“本质上即fit-content(stretch)min( max-content, max( min-content, stretch))”。

\n

stretch尝试“将 box\xe2\x80\x99s 边距框的大小与其包含块的大小相匹配。”
\n引用的“弹力尺寸”:

\n
\n

如果盒子的外部尺寸填满给定轴上的可用空间,则盒子将采用的尺寸;换句话说,如果确定的话,拉伸会适合可用空间。如果可用空间不确定,则未定义。

\n
\n

当我们在内联轴上工作时,网格的可用空间就是弹性容器的宽度。因此,弹性容器的宽度除非它真的很窄,在这种情况下,它将是min-content网格的大小(在这种情况下,每行中有一个项目,所有自动换行机会都被占用)。

\n

最大值是该大小与max-content网格大小的关系,在本例中,网格的大小是每行中的一个项目,每个项目的宽度都是所需的宽度。

\n
\n

max-content 内联大小\n内联轴中的 box\xe2\x80\x99s \xe2\x80\x9cideal\xe2\x80\x9d 大小。通常,如果没有采用盒子内的软包装机会,则在适合其内容物时可以采用的最窄内联尺寸。

\n
\n

所以,田田!此计算中网格的最终高度是我们在“行为不当”情况下看到的总高度。

\n

“弹性基础尺寸[我们在本节中试图找到的]是该项目的最终主要尺寸[我们刚刚计算的两个高度之一]。”

\n

由于没有最小和最大尺寸,因此最后两段不适用;柔性底座尺寸和假设的主要尺寸相同。

\n
\n
    \n
  1. 使用 Flex 容器参与的格式化上下文的规则确定 Flex 容器的主要大小。
  2. \n
\n
\n

正如前面所说,它的主要尺寸是它的高度。在这种情况下,格式化上下文是普通的旧流布局,其中高度基于内容;它将是其包含块的宽度。
\n因此,由于本例中只有一项,因此它将是我们上面计算的两个高度之一。

\n

如果是单行 Flex 容器,则该值为以 Flex 容器的全宽布局时网格容器的高度。
\n如果是多行弹性容器,则该值为应用布局时网格容器的高度width: fit-content

\n

这是我们看到的网格高度的差异,并且直接影响弹性容器的主要尺寸(高度)。

\n

这是弹性容器最终使用的高度!\n就是这个了!这就是为什么启用环绕会影响高度:它会阻止项目的横向尺寸被视为确定,这意味着它的高度的计算方式不同,

\n
\n

9.3. 主要尺寸确定

\n

这是物品的主要尺寸,包括灵活长度的分辨率(涉及flex-shrinkflex-grow)。

\n
\n
    \n
  1. 将弹性项目收集到弹性线中:
  2. \n
\n
\n

由于在本例中主要大小是根据内容(网格容器)计算的,因此我们只需要一行。在这种情况下,我们也只有一项,因此它始终只有一行。

\n
\n
    \n
  1. 解析所有柔性项目的柔性长度以找到其使用的主要尺寸。请参阅 \xc2\xa7\xe2\x80\xaf9.7 解析灵活长度。
  2. \n
\n
\n

由于 Flex 容器的主要尺寸当前基于内容,因此项目的尺寸不会改变。因此,网格容器使用的主要尺寸与其假设的主要尺寸/弹性基础尺寸相同,这是我们之前计算的。

\n
\n

9.4. 十字尺寸测定

\n
\n
    \n
  1. 通过执行布局来确定每个项目的假设交叉大小,就好像它是一个具有所使用的主大小和给定可用空间的流入块级框一样,将其auto视为fit-content
  2. \n
\n
\n

这就像width: fit-content使用应用来布局网格(没有指定宽度,因此它使用auto,被视为fit-content)。
\n请参阅第 9.2 节(“线长度确定”)的注释。

\n
\n
    \n
  1. 计算每条柔性线的交叉尺寸。
  2. \n
\n
\n
\n

如果 Flex 容器是单线且具有确定的交叉尺寸,则 Flex 线的交叉尺寸为 Flex 容器\xe2\x80\x99s 内交叉尺寸。

\n
\n

如果它是单行容器(即未启用换行),则适用。它有一个确定的十字尺寸(请参阅前面关于确定尺寸的注释)。因此,在这种情况下,唯一的柔性线的交叉尺寸将是柔性容器的内部交叉尺寸,即其包含块的宽度减去边距、边框和填充。

\n

如果是多行容器:

\n
\n

...对于每条柔性线:

\n
\n

我们只有一个。

\n

步骤 1 不适用(网格容器的内联轴不平行于主轴)。

\n
\n
    \n
  1. ...,找到最大的外部假设十字尺寸。
  2. \n
\n
\n

这是 7 中找到的尺寸的最大值,因此它将是布局时网格容器的宽度width: fit-content

\n
\n
    \n
  1. 所使用的柔性线的交叉尺寸是前两个步骤中找到的数字中最大的并且为零。
  2. \n
\n
\n

所以,仍然是 下网格容器的宽度width: fit-content

\n

现在我们有了线的使用的交叉尺寸(相同的宽度)。

\n
\n
    \n
  1. 处理“align-content:stretch”。如果 Flex 容器具有明确的交叉尺寸,则对齐内容会拉伸,并且 Flex 线的交叉尺寸之和小于 Flex 容器\xe2\x80\x99s 内部交叉尺寸,...
  2. \n
\n
\n

是的,它有一个确定的交叉尺寸,align-content是默认值stretch,并且Flex Lines的交叉尺寸之和小于Flex容器\xe2\x80\x99s内交叉尺寸:唯一的线\'交叉尺寸是width: fit-content网格的宽度,而弹性容器的内部交叉尺寸是其包含块的宽度减去边距和填充。

\n
\n

将每个柔性线的交叉尺寸增加等量,使得它们的交叉尺寸之和恰好等于柔性容器\xe2\x80\x99s的内部交叉尺寸。

\n
\n

只有一行,因此它只是扩展以填充弹性容器。线条的交叉尺寸现在是弹性容器的整个宽度。

\n

第 10 点不适用。

\n
\n
    \n
  1. 确定每个弹性项目所使用的交叉尺寸。如果弹性项目具有align-self: stretch,则其计算出的横向尺寸属性为auto,并且其横轴边距都不是auto, ...
  2. \n
\n
\n

是的,这适用。

\n
\n

...使用的外部十字尺寸是其柔性线的使用十字尺寸,根据 item\xe2\x80\x99s 使用的最小和最大十字尺寸进行夹紧。

\n
\n

因此,网格容器将水平拉伸到弹性容器的整个宽度。这适用于单行和多行柔性容器。

\n
\n

如果弹性项目具有align-self: stretch,则对其内容重新布局,将此使用的大小视为其确定的交叉大小,以便可以解析百分比大小的子项。

\n

请注意,此步骤不会影响弹性项目的主要尺寸,即使它具有首选的宽高比。

\n
\n

因此,该项目(网格容器)将重做其内容的布局,但其主要尺寸(高度)不会改变!

\n

本节实际上并没有根据 Flex 容器是单行还是多行做出任何区别,但它表明宽度始终相同,并且有关重做布局的部分很重要。

\n
\n

因此,网格将始终是 Flex 容器的内部交叉尺寸的宽度,即 Flex 容器的包含块的宽度减去边距、边框和填充。

\n

然而,由于确定的尺寸条款,高度取决于它是单行还是多行容器!

\n

所有这些确定/不定尺寸条件为什么设置显式宽度可以解决问题。
\n设置显式宽度意味着fit-content在计算网格容器的主要大小时使用它而不是使用它,这会给出预期的结果。

\n

谜团已揭开!

\n