内联块内的块元素在Firefox中表现奇怪

Eri*_*sch 5 css firefox

谁能在FF中解释这种行为?

小提琴:http://jsfiddle.net/4mrt8wq3/

<style>
    .b { display: inline-block; }
    #a { display: block; }
</style>

<div class="b">
    <label>xxxxxxxxxx</label> 
    <input type="text" id="a"/>
</div>
<div class="b">
    <label>xxxxxxxxxx</label>
    <div> / </div>
</div>
Run Code Online (Sandbox Code Playgroud)

仅在Firefox中,第一个div位于比第二个低一行的位置.它在Chrome和IE中正常工作(至少IE11).就好像内联块中的块元素由于某种原因包装在第二个元素下面.

使用溢出:隐藏在第一个div上修复了问题,但是第二个div然后稍微奇怪地定位,其上方有大约4或5个像素的边距.在两者上放置overflow-hidden会使其正确呈现.

我不是在寻找问题的解决方案,因为我已经找到了一个,但我无法解释这种行为...... 任何人都可以解释为什么这样做?

Alo*_*hci 7

是的,有趣的问题.首先,我们需要了解内联块元素的默认垂直对齐方式是基线,每个此类元素的基线是其中最后一个方框的基线.

在带有"b"类的第二个div中,内部div本身包含一个用于保存"/"字符的线框.然后,它为第二个div提供了类"b"的基线.

该基线必须与第一个div的基线对齐,并且类别为"b".问题变成:该div中最后一个行框的基线在哪里?

通过创建输入元素display:block,Firefox¹认为输入元素被"替换",它的内容对CSS是不透明的,因此输入元素不会创建任何行框.所以带有类"b"的第一个div的最后一行是包含标签的那一行,并且与'/'字符的行对齐.

Chrome采用了不同的视角.Chrome将输入元素视为具有CSS可见的内部结构,因此元素的内部形成一个线框,其基线随后成为第一个div的基线,类为"b",并且它与'/'字符.

当你添加`overflow:hidden'时,它会影响内联块的基线,使它们的基线不再是它们最后包含的线框的基线,并成为元素的下边距边缘.


哪种行为是正确的还不清楚.这取决于历史和被取代的元素的有点掺杂的概念.在浏览器的早期阶段,一些元素的呈现被委托给外部系统,即底层操作系统或插件.特别是,输入元素也是如此,其中渲染是通过O/S调用完成的.O/S没有CSS的概念,因此必须定义规则以允许有效的黑盒子与页面的其余部分进行交互.这些元素被归类为"替换"元素.

请注意这个定义的方式.没有正式的元素列表是替换元素,如果浏览器选择将其渲染委托给CSS世界之外的系统,则元素是替换元素,因此理论上你可以有两个浏览器,一个委托渲染元素和一个本地渲染它,并从CSS规则获得完全不同的交互.

随着浏览器的发展,他们停止委托他们对输入元素的渲染并自己渲染它,在渲染CSS的过程中.这会导致问题,因为现存的网页(假设输入元素将使用替换元素的规则呈现)可能变得不可用.如果浏览器允许这种情况发生,它将失去市场份额.因此,在大多数情况下,为了避免这种情况,浏览器实现这些元素的布局以与页面交互,就像它们被替换元素一样,即使实际上它们不是.

他们在这方面走得多远并没有明确规定.HTML5规范无法将表单控件识别为替换元素,并建议将它们呈现为内联块,这会使Chrome的行为正确,但是包括Chrome在内的所有浏览器都有很多种方式不会表现出来.从向后兼容性角度看旧Web内容,Firefox行为更可靠.

在表单控件的布局比当前情况更紧密地指定之前,不可能最终确定哪种行为是正确的.


¹ 对我来说,IE11的行为与Firefox类似.Opera 28(像Chrome这样的闪烁引擎)就像Chrome一样.Opera 12(presto引擎)的行为与Firefox类似.