父 flexbox 容器忽略孩子的 flexbox 最小宽度

Posted

技术标签:

【中文标题】父 flexbox 容器忽略孩子的 flexbox 最小宽度【英文标题】:Parent flexbox container ignores child's flexbox min-width 【发布时间】:2018-11-08 13:54:54 【问题描述】:

很短的史前史

我的故事始于努力让overflow-wrap: break-word; 在弹性盒中工作。 Flexbox 容器不想理解它的 item 可以缩小,尽管 item 可能会打断长词:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex-column 
  display: flex;


.item 
  overflow-wrap: break-word;
  background-color: #fff;
  padding: 8px;
<div class="body">
  <div class="flex-column">
    <div class="item">
      This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
    </div>
  </div>
</div>

幸运的是,我们可以帮助 flexbox 了解它可以在 item 上使用 min-width: 0; 来缩小其 item:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex-column 
  display: flex;


.item 
  overflow-wrap: break-word;
  background-color: #fff;
  padding: 8px;
  /* Okay, it fixes this */
  min-width: 0;
<div class="body">
  <div class="flex-column">
    <div class="item">
      This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
    </div>
  </div>
</div>

然而,现实世界要复杂一些。

问题

在我们的应用程序中,我们有许多嵌套的弹性盒。所以这个例子应该是这样的:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  min-width: 0;
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex">
    <div class="flex">
      <div class="flex">
        <div class="flex-column">
            <div class="item">
              This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

如您所见,flex-columnflex 容器忽略了它的子元素可以很好地收缩的事实。我不明白为什么它会这样。你能给我解释一下吗?为什么 flexbox-container 不尊重它的子 flexbox min-width: 0

我找到的解决方案是将min-width: 0 设置为层次结构中的所有 flexbox,这看起来非常笨拙和危险,因为我可以在意想不到的地方破坏我们的应用程序布局。

【问题讨论】:

【参考方案1】:

要理解这一点,只需为您的项目添加不同颜色的边框,您就会看到不同级别的溢出。更准确地说,在添加每个 min-width 后,我们只有一个溢出移动到较低的水平。

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex" style="border:5px solid red;">
    <div class="flex" style="border:5px solid green;">
      <div class="flex" style="border:5px solid blue;">
        <div class="flex-column" style="border:5px solid yellow;">
          <div class="item" style="border:5px solid pink;">
            This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
            your example looking how you want it to look. But both values are being rendered correctly.
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

每个min-width 都会修复一个溢出,允许元素缩小并将溢出移动到下一个级别。这就是为什么你需要一个级联的min-width

添加一个:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex" style="border:5px solid red;">
   <!-- adding min-width at this level -->
    <div class="flex" style="border:5px solid green;min-width:0;">
      <div class="flex" style="border:5px solid blue;">
        <div class="flex-column" style="border:5px solid yellow;">
            <div class="item" style="border:5px solid pink;">
              This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get your example looking how you want it to look. But both values are being rendered correctly.
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

添加另一个:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex" style="border:5px solid red;">
    <div class="flex" style="border:5px solid green;min-width:0;">
      <!-- adding min-width at this level -->
      <div class="flex" style="border:5px solid blue;min-width:0">
        <div class="flex-column" style="border:5px solid yellow;">
          <div class="item" style="border:5px solid pink;">
            This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
            your example looking how you want it to look. But both values are being rendered correctly.
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

再次:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex" style="border:5px solid red;">
    <div class="flex" style="border:5px solid green;min-width:0;">
      <div class="flex" style="border:5px solid blue;min-width:0">
       <!-- adding min-width at this level -->
        <div class="flex-column" style="border:5px solid yellow;min-width:0;">
          <div class="item" style="border:5px solid pink;">
            This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
            your example looking how you want it to look. But both values are being rendered correctly.
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

最后一个:

.body 
  width: 300px;
  border: 1px solid black;
  padding: 8px;
  background-color: #ccc;


.flex 
  display: flex;


.flex-column 
  display: flex;


.item 
  padding: 8px;
  background-color: #fff;
  overflow-wrap: break-word;
<div class="body">
  <div class="flex" style="border:5px solid red;">
    <div class="flex" style="border:5px solid green;min-width:0;">
      <div class="flex" style="border:5px solid blue;min-width:0">
        <div class="flex-column" style="border:5px solid yellow;min-width:0;">
         <!-- adding min-width at this level -->
          <div class="item" style="border:5px solid pink;min-width:0">
            This is Spaaaaaaaaaaaaaaaarrrrrrrrrrrrrttttttttttttttaaaaaaaaaaaaaaaaaaaaaa!11 It's not a bug. Firefox is correctly implementing min-width: auto for flex items. When you change it to min-width: 0, you're just using a different value for min-width to get
            your example looking how you want it to look. But both values are being rendered correctly.
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

【讨论】:

感谢您的回答!您的带边框示例很棒,可以更好地理解问题。但是,我仍然不明白为什么祖父母 flex “知道” 有一些溢出的孙子?为什么将min-width: 0 设置在最深层次还不够?我认为 flexbox 容器应该“问”它的孩子:——你能缩小多远? — 我可以很好地收缩,因为我的孩子有min-width: 0。 — 好吧,我想我也可以缩小,因为你是我唯一的孩子,你可以缩小到 0。所以我认为它应该从下到上递归地工作。 @algebraic 因为在最深层没有溢出。如果你检查好边界,你会看到绿色溢出红色(这是我们的溢出),然后在我们没有溢出之后(添加 min-width 不会做任何事情)。所以我们没有很多溢出,但只有一个不同级别的溢出。如果您修复第一个,您将缩小一个边框并将溢出移动到较低的级别,依此类推。所以第一个不会缩小,之后一切正常。如果第一个缩小,我们将问题转移到它的孩子 我真的建议你在 sn-p 的 CSS 端添加额外的 CSS;我看了好几眼才弄清楚你的 sn-ps 之间有何不同,因为它们的 CSS 部分都是相同的。 @algebraic 从底层开始思考。最后一个元素有内容,没有宽度限制(没关系)。它的父级也没有宽度限制(仍然很好并且没有溢出)..直到我们到达具有宽度限制的元素,这里我们有溢出,因为我们不允许收缩......所以允许在发生过低的地方收缩修复问题,您可以从底部重新开始逻辑,您将到达我们再次修复的溢出点,依此类推。 @TylerH,我想我应该把重复的class="flex" 换成更有意义的东西,谢谢!问题更多是关于“为什么它以这种方式工作?”。当然,我对如何修复它很感兴趣,但它确实特定于我的应用程序层次结构,并且很难在这里重现它。为了简化问题:想象一下,从&lt;div class="flex-column"&gt;开始的代码sn-p被提取到react组件中,可以插入到任何容器中(包括固定宽度的块div,里面有flex)。如何保证它不会溢出父级?

以上是关于父 flexbox 容器忽略孩子的 flexbox 最小宽度的主要内容,如果未能解决你的问题,请参考以下文章

Flexbox最后一个子边距在Firefox中折叠

嵌套弹性容器时正确使用弹性属性

Flexbox溢出未在Chrome中扩展父容器

flexbox下的孩子没有指定宽度[重复]

Flexbox 中的第一个孩子全角

flexbox边距在孩子之间折叠[重复]