<div style = "float : left; background-color: #dd3fb8;">
<a style = "margin-left : 10%;">a</a>
<a>b</a>
<a>c</a>
</div>
在上面的例子中,字母&#34; c&#34;会在新线上,但如果我设置&#34; margin-left&#34;到px单位,&#34; c&#34;将与&#34; a&#34;在同一条线上和&#34; b&#34;。为什么会这样?
答案 0 :(得分:13)
不幸的是,CSS2.1规范似乎没有明确的答案。事实上,我会说这完全属于未定义的行为。
以下是我能找到的相关观点:
没有指定宽度的浮点数将为shrink to fit their contents。对于仅具有内联内容的浮动,浮动需要做得足够宽以使其内容适合单行(尽管有明确的换行符)而不再需要。
百分比边距的计算为based on the width of the containing block。
请注意:
如果包含块的宽度取决于此元素,则在CSS 2.1中未定义结果布局。
...但据我所知,所有浏览器的行为都是一致的。
话虽如此,这句话适用的原因是因为内联元素的边距落在float的内容边界内,可以说float的宽度(内联元素的包含块)取决于在这个元素(具有边距的元素)上。
根据以上几点,我可以演绎:
当保证金指定为百分比时,浮动的宽度是在不考虑保证金的情况下计算的,因为无法计算保证金直到浮动的宽度已确定。
然后根据浮动的使用宽度计算边距,并且字母“c”由于被“a”上的边距向前推动而换行到新线。 浮动的宽度不会改变。
同样,根本没有指定这种行为,因此从技术上讲,它并没有违反规范。但是,这似乎是明智的。
当将边距指定为像素值时,首先计算边距。然后考虑此边距计算浮动的宽度(请记住,水平边距确实适用于内联元素)。根据收缩拟合算法,这是首选宽度:宽度足以包含单行上的所有内联元素。
与百分比边距不同,这是非常明确的,因为实现应该首先计算边际的计算绝对值没有问题。
我很难在任何浏览器中将其称为错误,特别是因为它们都表现得一致。
最后,当然,您可以完全避免这种未定义的行为,只需在可能的情况下给浮动显式宽度。但是,它确实有助于理解为什么应该这样做。
答案 1 :(得分:9)
由于div
已展开,其width
为auto
(隐式),http://www.w3.org/TR/CSS21/visudet.html#float-width适用:
如果'width'计算为'auto',则使用的值为“shrink-to-fit”宽度。
“缩小到适合”宽度基本上意味着,让元素与其内容所需的宽度一样宽。
现在没有margin-left
,这没有问题:所有三个a
元素都是内联元素,每个元素都包含一个特定的字符 - 足以确定它们各自的宽度,并将它们相加。
但现在你想要一个margin-left
百分比,这里的事情变得复杂 - 如果我们看一下the definition for margin-left
,它会说:
百分比:指包含块的宽度
现在,由于包含块(由浮动的div
元素建立)的宽度是基于其内容计算的,因此我们在中留下了一些pickle - 但是现在这个margin-left
将更改该内容的总宽度,但它本身依赖于包含块的width
,它本身会影响...
这是两个依赖相互依赖的测量的经典问题 ......基本上不可解决。
http://www.w3.org/TR/CSS21/box.html#margin-properties说,
百分比是根据生成的框的包含块的宽度计算的。 [...]
如果包含块的宽度取决于此元素,则在CSS 2.1中未定义结果布局。
编辑:基本上与BoltClock在答案中所说的相同,只是花了我一点时间......
答案 2 :(得分:4)
该链接的左边距为10%, 多少 的10%?父元素向左浮动,这意味着它没有自己的宽度,而是扩展其内容。如果您试图模仿浏览器计算结果框的方式,您会发现自己处于修复状态:
这会创建一个循环,其中边距随着外部宽度的增加而增加,外部宽度随着边距的增加而增加(33px的10%= 3.3px意味着容器宽度从33px变为33.3xx,依此类推)。对于此类计算,结果行为未定义(由CBroe指出)。
浏览器似乎避开了循环并以30px宽度粘贴。计算后引入的3px余量导致第三个链接流入第二行。浏览器再次通过坚持30px宽度来避免循环。