#a {
display: inline-block;
}
#b {
float: left;
}
#c {
display: block;
overflow: hidden;
}

<span id="a">
<span id="b">b</span>
<span id="c">c1 c2</span>
</span>
&#13;
在Chrome和IE上,它会呈现为:
然而,Firefox将其呈现为:
您可以在this jsFiddle中尝试。
这里只是一些背景,没有它,我在上面尝试做的事情似乎很疯狂。我打算将上述块用于标签,例如:
元素#a
,#b
和#c
对应于:
CSS旨在处理以下约束:
答案 0 :(得分:7)
不要混在一起,拥抱桌子!
&#34;修正&#34;它在Firefox(测试31.2.0)和IE 8上,老实说在语义上更正确。
.a{ display:inline-table; max-width:45%; }
.b{ display:table-cell; padding-right:5px;}
.c{ display:table-cell; }
&#13;
<span class="a">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<br /><hr /><br />
<span class="a">
<span class="b">longer</span>
<span class="c">Bacon ipsum dolor amet excepteur laboris irure, corned beef minim pastrami venison in anim incididunt strip steak ea non doner.</span>
</span>
&#13;
原始代码的问题在于Firefox在计算缩小尺寸时会使浮动元素完全脱离流量。虽然float
会影响流入内容宽度,但它们本身并不会流入,因此只是从内容的其余部分获取水平空间 - 导致您看到的行为
以下是对正在发生的事情的演示(在Firefox中实际查看它的视图)。请注意,outline
和.a
上使用的是.c
,border
上使用的是.b
{实际占用空间}。
.a { display: inline-block; outline: 1px solid blue; }
.b { float: left; border: 5px solid green; }
.c { display: table; outline: 1px solid red; }
&#13;
<span class="a">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<br />
<span class="c">c1 c2</span>
&#13;
这是设计使用,而不是错误,并且检查the current spec,the basic box model working draft和the spec regarding calculating widths您会发现浮动广告被标记为out-of-flow和the spec regarding block-formatting and inline-formatting明确指出float
是内联上下文宽度的一部分,但不适用于块上下文(inline-block
的内部)。因此,Firefox实际上是根据对规范的严格解释来表现的 - 这在技术上是其他浏览器中的一个错误。
然而,Firefox仍然存在这样的问题。
如果我们使浮动大于我们的流入内容(并切换回边界,因为轮廓包括溢出的孩子;我已经将兄弟红色向左移动了1px,因此它将与其侄子克隆对齐)(再次,在Firefox中查看)
.a { display: inline-block; border: 1px solid blue; }
.b { float: left; border: 5px solid green; width:200px; }
.c { display: table; border: 1px solid red; }
.d { position:relative; left:1px; }
.e { max-width:100px; }
&#13;
<span class="a">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<br />
<span class="c d">c1 c2</span>
<br />
^^^ without <em>.a</em> having a width limit
<hr />
vvv with <em>.a</em> having a width limit
<br />
<span class="a e">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<br />
<span class="c d">c1 c2</span>
&#13;
蓝色框被拉伸以包含其整个绿色孩子,尽管根据the spec的严格解释,它应该溢出。这是Firefox的一个错误,因为浮点数只会影响内联上下文中的父width:auto
。在块上下文中,inline-block
的内部应该是,不包括浮点数的宽度。
请注意,这也是大多数其他浏览器的行为方式(在某种程度上 - Firefox会将父级的大小调整为float
的框宽度,而其他浏览器会将插入内容放在旁边如果父级仍然可以增长,并且如果您在width
(在我的示例中为ala .a
)提供任何.e
值或限制,则会获得预期的行为(如图所示)绿色浮动溢出其父级(在所有浏览器中应该是这种情况,因为所有这些行为问题都基于width:auto
)。
Oriol的许多啤酒(另一个答案的海报) - 如果我没有开始与他争论,我就没有理由真正进入规格和数字是什么真的正在发生。同样值得称道的是,他指出Firefox仍然错误地渲染它 - 整个部分都归功于他。
答案 1 :(得分:0)
根据inline-block width,#a
的宽度是使用缩小拟合算法计算的:
如果
width
为auto
,则使用的值为shrink-to-fit宽度
shrink-to-fit algorithm(现在称为fit-content measure)
min(max-content,max(min-content,fill-available))
这意味着,如果有足够的空间,其宽度将是内容的最大首选宽度(也就是说,除了发生显式换行之外,不会破坏行)。否则,它将与可用空间一样宽。
然后,浏览器首先计算#a
的首选宽度。
通常,浮动在块框之后重叠,如Floats:
中所述由于浮动不在流中,因此创建了未定位的块框 在浮动箱垂直流动之前和之后,好像浮子没有 存在。
然后,Firefox似乎计算出首选宽度,好像#b
和#c
可能重叠。因此,首选宽度是浮动#b
宽度的最大值和#c
的宽度。
但是,由于#c
,overflow: hidden
建立了新的block formatting context(BFC):
使用&溢出&#39;阻止框除了&#39;可见&#39; [...]建立新的 阻止格式化其内容的上下文。
在你的小提琴中,#c
是一张表,但它是相同的,因为,如Tables model中所定义,
表包装器框建立块格式化上下文。
但正如BFC next to floats中所解释的那样,BFC根不能重叠浮点数:
表的边框,块级替换元素或 正常流程中的元素,用于建立新的块格式 上下文(例如带有溢出&#39;除了&#39;可见&#39;之外的元素)必须 不与同一块格式中任何浮点数的边距框重叠 上下文作为元素本身。
相反,浮动可以&#34;推动&#34; BFC在右边。这就是为什么在Chrome和Edge上,#a
的首选宽度是#b
和#c
的首选宽度的总和。
#a
的宽度将是上一步计算的首选宽度,以防它不大于可用宽度。
否则,浏览器会在#b
和#c
之间引入换行符来计算首选的最小宽度。因此,它将是#b
和#c
的最小首选宽度的最大值。 #a
的最终宽度将是该首选最小宽度与可用宽度之间的最大宽度。
现在#a
的宽度已经解决,因此#b
和#c
的宽度也可以解析。
由于#b
已浮动,因此也会使用缩小到适合算法进行调整。
如果#c
是一个块,它将占用剩余空间(如果没有可用空间,它将被移动到下一行)。如果它是一个表,则默认的automatic table layout算法取决于实现,但类似于缩小到适合。结果基本相同。
对于Chrome和Edge,如果空间足够,#c
占用的剩余空间是其首选宽度,因为#a
的首选宽度是#b
的总和和#c
。
然而,Firefox使用了最大值。因此,如果#b
宽于#c
,#b
将完全填充#a
,#c
将移至下一行。如果#c
宽于#b
,则#b
旁边会有一些剩余空间,因此#c
会缩小以适应那里。收缩导致#c
小于其首选宽度(即使#a
有可用空间增长更多),因此某些换行符将显示在#c
中。
Chrome和Edge首先检测BFC根不会与浮点重叠,然后内联块父级的宽度成为浮点数和BFC根的总和。
相反,Firefox最初将BFC根看作普通块,它认为它将与浮点重叠,并相应地计算父级的宽度。然后检测它是否是BFC根,防止重叠,并缩小它以适应剩余的空间。
所以区别似乎是他们计算父级的宽度并防止BFC根以不同的顺序重叠浮动。
不正确的行为似乎是Firefox的。如Intrinsic Sizes of Non-Replaced Blocks中所定义,首选宽度应在布局后计算,并且最可能的布局包括在浮动旁边推送BFC根。
块容器框的max-content measure是 如果所有孩子的大小都在a。下,则在布局后测量框 max-size constraint
在display: inline-block
上使用display: inline-table
或#c
等内嵌级别显示会使Firefox在计算{#b
宽度时加总#c
和#a
的宽度{1}}。这样,如果有足够的可用空间,#c
不会缩小,也不会出现换行符。
问题在于,如果内联级别的内容太宽而无法放入浮动所留下的剩余空间,则内联级别将移动到下一行而不是收缩。
.a { display: inline-block; }
.b { float: left; }
.c { display: inline-table; }
&#13;
<span class="a">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<hr />
<span class="a">
<span class="b">longer</span>
<span class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis diam nec ligula iaculis lacinia non ac neque. Vivamus ut condimentum enim, et sollicitudin magna. In rhoncus nisi at est rhoncus feugiat sed vitae lacus. Maecenas sed felis et libero posuere iaculis a in lacus. Quisque eleifend auctor metus, a congue sapien venenatis a. Duis mollis mauris vitae massa mollis, nec porta nulla semper. Proin fringilla et nibh ac tempor. Aenean et augue ut dui pharetra scelerisque sed sit amet dolor. Nulla posuere a lorem sit amet vehicula. Morbi nec lacinia nibh. Suspendisse lacus nulla, dignissim et mi ut, luctus lobortis nisl. </span>
</span>
&#13;
或者,如果旧浏览器支持不是问题,则可以使用flexbox。一个简单的#a { display: inline-flex; }
基本上可以工作,但以下内容更接近您当前的代码。
.a {
display: inline-flex;
align-items: flex-start;
flex-wrap: wrap; /* Allow line breaks if #b is too wide */
}
.c {
flex: 1; /* Initial width of 0, then take remaining space left by #b */
}
&#13;
<span class="a">
<span class="b">b</span>
<span class="c">c1 c2</span>
</span>
<hr />
<span class="a">
<span class="b">longer</span>
<span class="c">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut quis diam nec ligula iaculis lacinia non ac neque. Vivamus ut condimentum enim, et sollicitudin magna. In rhoncus nisi at est rhoncus feugiat sed vitae lacus. Maecenas sed felis et libero posuere iaculis a in lacus. Quisque eleifend auctor metus, a congue sapien venenatis a. Duis mollis mauris vitae massa mollis, nec porta nulla semper. Proin fringilla et nibh ac tempor. Aenean et augue ut dui pharetra scelerisque sed sit amet dolor. Nulla posuere a lorem sit amet vehicula. Morbi nec lacinia nibh. Suspendisse lacus nulla, dignissim et mi ut, luctus lobortis nisl. </span>
</span>
&#13;