flexbox/网格布局中的最后边距/填充折叠

新手上路,请多包涵

我有一个项目列表,我试图用 flexbox 将它们排列成可滚动的水平布局。

容器中的每个项目都有左右边距,但最后一个项目的右边距正在折叠。

有没有办法阻止这种情况的发生,或者一个好的解决方法?

 ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 300px;
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
  margin: 0 30px;
  white-space: nowrap;
  flex-basis: auto;
}
 <div class="container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>

原文由 Kevin Wilson 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 250
1 个回答

潜在问题 #1

最后一个保证金没有被折叠。它被忽略了。

overflow 属性仅适用于 内容。它不适用于填充或边距。

这是规范中的内容:

11.1.1 溢出: overflow 属性

此属性指定块容器元素的内容在溢出元素的框时是否被剪裁。

现在让我们看一下 CSS 盒模型

在此处输入图像描述

来源: W3C

overflow 属性仅限于内容框区域。如果内容溢出其容器,则适用 overflow 。但是 overflow 没有进入填充或边距区域(当然,除非后面有更多内容)。


潜在问题#2

Potential Problem #1 的问题在于它似乎在 flex 或 grid 格式化上下文之外崩溃了。例如,在标准块布局中,最后一个边距似乎没有折叠。所以也许 overflow 被允许覆盖边距/填充,不管它在规范中说了什么。

 div {
  height: 150px;
  overflow: auto;
  width: 600px;
  background: orange;
  white-space: nowrap;
}
span {
  background: blue;
  color: #fff;
  padding: 50px;
  margin: 0 30px;
  display: inline-block;
}
 <div class="container">
    <span>Item 1</span>
    <span>Item 2</span>
    <span>Item 3</span>
    <span>Item 4</span>
</div>

因此,问题可能与“过度约束”的元素有关。

10.3.3 正常流程中的块级、非替换元素

以下约束必须包含在其他属性的使用值中:

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = 包含块的宽度

If width is not auto and border-left-width + padding-left + width + padding-right + border-right-width (plus any of margin-left or margin-right that are not auto ) is larger than the width of the containing block, then any auto margin-leftmargin-right 的值,对于以下规则,被视为零。

如果以上所有项的计算值不是 auto ,则这些值被称为“过度约束”,并且使用的值之一必须与其计算值不同。如果包含块的 direction 属性的值为 ltr ,则 margin-right 的指定值将被忽略,从而计算出相等性. 如果 direction 的值是 rtl ,这恰好是 margin-left

(强调)

因此,根据 CSS Visual Formatting Model ,元素可能会“过度受限”,因此右边距会被丢弃。


潜在的解决方法

在最后一个元素上使用右边 ,而不是边距或填充:

 li:last-child {
  border-right: 30px solid orange;
}

 ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 100px; /* adjusted for demo */
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
  margin: 0 30px;
  white-space: nowrap;
  flex-basis: auto;
}
li:last-child {
  border-right: 30px solid orange;
}
 <ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

另一种解决方案使用 伪元素 代替边距或填充。

弹性容器上的伪元素呈现为弹性项目。容器中的第一项是 ::before 最后一项是 ::after

 ul::after {
  content: "";
  flex: 0 0 30px;
}

 ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  height: 100px; /* adjusted for demo */
  overflow: auto;
  width: 600px;
  background: orange;
}
ul li {
  margin: 0 30px;
  background: blue;
  color: #fff;
  padding: 90px;
  white-space: nowrap;
  flex-basis: auto;
}
ul::after {
  content: "";
  flex: 0 0 30px;
}

ul::before {
  content: "";
  flex: 0 0 30px;
}
 <ul>
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
  <li>Item 4</li>
</ul>

原文由 Michael Benjamin 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题