Flexbox /网格布局中的上一个边距/填充折叠

时间:2016-08-17 09:45:33

标签: html css css3 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>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:28)

潜在问题#1

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

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

以下是规范中的内容:

  

11.1.1 Overflow: the overflow property

     

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

现在让我们来看看CSS Box Model

enter image description here

来源:W3C

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

潜在问题#2

潜在问题#1的问题在于它似乎在弹性或网格格式化上下文之外崩溃。例如,在标准块布局中,最后一个边距似乎不会崩溃。因此,无论规范中的内容如何,​​都可以允许overflow覆盖边距/填充。

&#13;
&#13;
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;
}
&#13;
<div class="container">
    <span>Item 1</span>
    <span>Item 2</span>
    <span>Item 3</span>
    <span>Item 4</span>
</div>
&#13;
&#13;
&#13;

因此,问题可能与过度约束的元素有关。&#34;

  

10.3.3 Block-level, non-replaced elements in normal flow

     

以下约束必须包含在另一个的使用值中   属性:

     

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

     

如果width不是autoborder-left-width + padding-left +   width + padding-right + border-right-width(以及任何   不margin-left的{​​{1}}或margin-right大于   包含块的宽度,然后是auto的任何值   对于以下规则,automargin-left会受到处理   为零。

     

如果上述所有内容都具有margin-right以外的计算值,则表示这些值为&#34;过度约束&#34;和其中一个使用的值   必须与其计算值不同。如果auto   包含块的属性具有值direction,指定的值   忽略ltr的值,并计算该值   使等式成立。 如果margin-right的值为direction,   这恰好发生在rtl

     

(强调补充)

因此,根据CSS Visual Formatting Model,元素可能会过度约束&#34;结果,右边距被抛出。

潜在的解决方法

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

margin-left

&#13;
&#13;
li:last-child {
  border-right: 30px solid orange;
}
&#13;
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;
}
&#13;
&#13;
&#13;

另一种解决方案使用伪元素而不是边距或填充。

Flex容器上的伪元素呈现为弹性项目。容器中的第一项是<ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> </ul>,最后一项是::before

::after

&#13;
&#13;
ul::after {
  content: "";
  flex: 0 0 30px;
}
&#13;
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;
}
&#13;
&#13;
&#13;

答案 1 :(得分:4)

你的问题本身不是保证金。它是滚动条,仅标注元素的可见内容。

解决问题的一个方法是创建一个占据边距的可见元素

此解决方案使用最后一个孩子的伪

处理此问题

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;
  position: relative;
}
li:last-child:after {
  content: "";
  width: 30px;
  height: 1px;
  position: absolute;
  left: 100%;
  top: 0px;
}
<div class"container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>

答案 2 :(得分:2)

您可以在width容器上设置overflowdiv,并在display: inline-flex上设置flex而不是ul,以便弹性框的大小将根据内部的项目计算,所有填充和边距将适用,没有任何问题。

.container {
  width: 600px;
  overflow: auto;
}

.container ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: inline-flex;
  background: orange;
}

.container li {
  padding: 60px;
  margin: 0 30px;
  white-space: nowrap;
  background: blue;
  color: #fff;
}
<div class="container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>

答案 3 :(得分:-2)

查看解决方案。我删除white-spaceflex-basismargin,为您提供纯粹的flexbox解决方案。

它会转发flex-flow: row(水平),justify-content: space-around(您的保证金),而不再发布! width更改为1200px,因为90px的填充设置了框的总宽度超过600px(在您的代码段中定义)。

ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-flow: row ;
  justify-content: space-around;
  height: 300px;
  overflow: auto;
  width: 1200px;
  background: orange;
}
ul li {
  background: blue;
  color: #fff;
  padding: 90px;
}
<div class"container">
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
  </ul>
</div>