上次保证金/填充折叠在flexbox中 [英] Last margin / padding collapsing in flexbox
问题描述
容器中的每个项目都有一个左右边距,但最后一个项目的右边缘正在被折叠。
有没有办法阻止这种情况发生,或者一个很好的解决方法?
问题原因: http://codepen.io/anon/pen/WxmdpN
ul {list-style-type:none;填充:0;保证金:0;显示:flex;身高:300px;溢出:自动;宽度:600px;背景:橙色;} UL LI {背景:蓝色;颜色:#fff;填充:90px; margin:0 30px;白色空间:nowrap; flex-basis:auto;}
< div class容器> < UL> < li>第1项< / li> < li>第2项< / li> < li>第3项< / li> < li>第4项< / li> < / ul>< / div>
不用进行大量的实验,我会建议这个行为在spec中定义:
以下约束条件必须适用于其他
属性:
$ p $ margin $ margin $ left $ width $ border-left-width +padding-left
+width
+
padding -right +
border-right-width
+margin-right
= $ b的宽度$ b包含block $ /
如果
width
不是auto
和border-left-width
+padding-left
+
width +
padding-right
+border-right-width
(加上任何
margin-left
或margin-right
不是auto
)大于
包含块的宽度,则
margin-left
或margin-right $
auto
c $ c>对于以下规则,将
作为零处理。
如果以上所有都有一个计算值other比
auto
,这些值被认为是过度约束的,而其中一个使用的值
必须和它的计算值不同。如果包含块的direction
属性的值为ltr
,则指定的
值margin-right
会被忽略,并且计算该值的值为
以使相等为真。 如果方向
是rtl
,
这恰好是margin-left
改为
(强调增加)
所以,根据< CSS视觉格式模型,你的包含块可能是过度约束,并且,结果,一个右边距被抛出。
解决方案
一个解决方案是在最后一个元素上添加一个正确的 border :
li:last -child {
border-right:30px纯橙色;
$ b
<覆盖> ul {list-style-type:none;填充:0;保证金:0;显示:flex;身高:300px;溢出:自动;宽度:600px;背景:橙色;} UL LI {背景:蓝色;颜色:#fff;填充:90px; margin:0 30px;白色空间:nowrap; flex-basis:auto;} li:last-child {border-right:30px solid orange;}
< UL> < li>第1项< / li> < li>第2项< / li> < li>第3项< / li> < li>项目4< / li>< / ul>
p>另一个解决方案使用伪元素而不是边距(或填充)。
flex容器上的伪元素呈现为flex项目。容器中的第一项是 :: before
,最后一项是 :: after
。
ul :: after {
content:;
flex:0 0 30px;
$ b
<覆盖> ul {list-style-type:none;填充:0;保证金:0;显示:flex;身高:300px;溢出:自动;宽度:600px;背景:橙色;} UL李{margin:0 30px;背景:蓝色;颜色:#fff;填充:90px;白色空间:nowrap; flex-basis:auto;} ul :: after {content:; flex:0 0 30px;} ul :: before {content:; flex:0 0 30px;}
< ul> < li>第1项< / li> < li>第2项< / li> < li>第3项< / li> < li>第4项< / li>< / ul>
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?
Codepen of issue: http://codepen.io/anon/pen/WxmdpN
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>
解决方案 The Problem
This appears to be the default behavior on all major browsers: In testing, the right margin collapses in Firefox, Chrome, Safari, IE11 and Edge.
Without going into a lot of experimentation, I'll suggest that this behavior is defined in the spec:
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, your containing block may be "over-constrained" and, as a result, a right margin gets tossed out.
Solutions
One solution is to add a right border to your last element:
li:last-child {
border-right: 30px solid orange;
}
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;
}
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: 300px;
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>
这篇关于上次保证金/填充折叠在flexbox中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文