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

时间:2015-04-24 22:21:26

标签: 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>

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

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

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

2 个答案:

答案 0 :(得分:5)

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

在带有“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类似。

答案 1 :(得分:0)

您的问题是每个规格设置溢出:隐藏会更改内联块的基线位置。 Firefox实现了规范所说的内容。 Chrome没有。

解决方案:

<style>
  .b { display: inline-block; 
  vertical-align: top; /*add this line */
  }
  #a { display: block; }
</style>