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

标签 html css flexbox css-grid

我有一个元素列表,我正在尝试使用 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>

最佳答案

潜在问题#1

最后一个边距没有折叠。它被忽略了。

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

这是规范中的内容:

11.1.1 Overflow: the overflow property

This property specifies whether content of a block container element is clipped when it overflows the element's box.

现在让我们看一下 CSS Box Model :

enter image description here

来源:W3C

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


潜在问题 #2

潜在问题 #1 的问题在于它似乎在 flex 或网格格式上下文之外崩溃了。例如,在标准 block 布局中,最后一个边距似乎没有折叠。所以也许 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 Block-level, non-replaced elements in normal flow

The following constraints must hold among the used values of the other properties:

margin-left + border-left-width + padding-left + width + padding-right + border-right-width + margin-right = width of containing block

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 values for margin-left or margin-right are, for the following rules, treated as zero.

If all of the above have a computed value other than auto, the values are said to be "over-constrained" and one of the used values will have to be different from its computed value. If the direction property of the containing block has the value ltr, the specified value of margin-right is ignored and the value is calculated so as to make the equality true. If the value of direction is rtl, this happens to margin-left instead

(emphasis added)

所以,根据 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>

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

flex 容器上的伪元素呈现为 flex 元素。容器中的第一项是 ::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>

关于html - flexbox/网格布局中的最后边距/填充折叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45681599/

相关文章:

css动画如何让球反弹

html - 在 Bootstrap 4 flexbox 中创建等高的 div

jquery - Bootstrap 下拉菜单 : events for the 'navbar-toggle' ?

php - 如何使滚动条出现在div的边框内

html - 无论文本长度如何,都将单选按钮居中对齐

css - 使用 css 文件设置根元素样式,但不起作用

html - Flexbox 断点对两列没有响应

css - 使用 grid/flex 使行之间的列大小均匀

html 元标记在其他页面中不起作用

javascript - 如何将 HTML 页面下载为图像?