弹性盒/网格布局中的最后一个边距/填充折叠 [英] Last margin / padding collapsing in flexbox / grid layout

查看:28
本文介绍了弹性盒/网格布局中的最后一个边距/填充折叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目列表,我试图将这些项目排列成带有 flexbox 的可滚动水平布局.

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

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

ul {列表样式类型:无;填充:0;边距:0;显示:弹性;高度:300px;溢出:自动;宽度:600px;背景:橙色;}乌利{背景:蓝色;颜色:#fff;填充:90px;边距:0 30px;空白:nowrap;弹性基础:自动;}

<ul><li>项目 1</li><li>项目 2</li><li>项目 3</li><li>项目 4</li>

解决方案

潜在问题 #1

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

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

这是规范中的内容:

<块引用>

来源:W3C

overflow 属性仅限于内容框区域.如果内容溢出其容器,则应用 overflow.但是 overflow 不会进入 padding 或 margin 区域(当然,除非后面有更多内容).

<小时>

潜在问题#2

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

div {高度:150px;溢出:自动;宽度:600px;背景:橙色;空白:nowrap;}跨度 {背景:蓝色;颜色:#fff;填充:50px;边距:0 30px;显示:内联块;}

<span>项目 1</span><span>项目 2</span><span>项目 3</span><span>项目 4</span>

因此,问题可能与过度约束"的元素有关.

<块引用>

10.3.3 普通中的块级非替换元素流量

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

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-leftmargin-right 不是 auto) 大于包含块的宽度,然后是任何 automargin-leftmargin-right 对于以下规则,处理为零.

如果上述所有值都具有除 auto 之外的计算值,则这些值被称为过度约束"并且是使用的值之一必须与其计算值不同.如果方向包含块的属性具有值 ltr,指定的margin-right 的值被忽略并计算为使等式成立.如果direction的值为rtl,这发生在 margin-left

(强调)

因此,根据 CSS 视觉格式模型,元素可能是过度约束",结果,右边距被丢弃.

<小时>

潜在的解决方法

在最后一个元素上使用右边框代替边距或填充:

li:last-child {右边框:30px 纯橙色;}

ul {列表样式类型:无;填充:0;边距:0;显示:弹性;高度:100px;/* 为演示调整 */溢出:自动;宽度:600px;背景:橙色;}乌利{背景:蓝色;颜色:#fff;填充:90px;边距:0 30px;空白:nowrap;弹性基础:自动;}李:最后一个孩子{右边框:30px 纯橙色;}

    <li>项目 1</li><li>项目 2</li><li>项目 3</li><li>项目 4</li>

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

flex 容器上的伪元素被渲染为 flex 项目.容器中的第一项是::before,最后一项是::after.

ul::after {内容: "";弹性:0 0 30px;}

ul {列表样式类型:无;填充:0;边距:0;显示:弹性;高度:100px;/* 为演示调整 */溢出:自动;宽度:600px;背景:橙色;}乌利{边距:0 30px;背景:蓝色;颜色:#fff;填充:90px;空白:nowrap;弹性基础:自动;}ul::after {内容: "";弹性:0 0 30px;}ul::before {内容: "";弹性:0 0 30px;}

    <li>项目 1</li><li>项目 2</li><li>项目 3</li><li>项目 4</li>

I have a list of items that I'm trying to arrange into a scrollable horizontal layout with flexbox.

Each item in the container has a margin left and right, but the right margin of the last item is being collapsed.

Is there a way to stop this happening, or a good workaround?

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>

解决方案

Potential Problem #1

The last margin is not being collapsed. It's being ignored.

The overflow property applies only to content. It doesn't apply to padding or margins.

Here's what it says in the spec:

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.

Now let's take a look at the CSS Box Model:

source: W3C

The overflow property is limited to the content box area. If the content overflows its container, then overflow applies. But overflow doesn't enter into the padding or margin areas (unless, of course, there is more content that follows).


Potential Problem #2

The problem with Potential Problem #1 is that it appears to fall apart outside of a flex or grid formatting context. For example, in a standard block layout, the last margin doesn't appear to collapse. So maybe overflow is permitted to cover margins / paddings, regardless of what it says in the spec.

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>

Hence, maybe the problem is instead related to elements that are "over-constrained".

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)

So, according to the CSS Visual Formatting Model, elements may be "over-constrained" and, as a result, a right margin gets tossed out.


Potential Workarounds

Instead of margin or padding, use a right border on the last element:

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>

Another solution uses a pseudo-elements instead of margins or padding.

Pseudo-elements on a flex container are rendered as flex items. The first item in the container is ::before and last item is ::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>

这篇关于弹性盒/网格布局中的最后一个边距/填充折叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆