<div id="test">
<i>test</i>
</div>
var test = document.getElementById("test");
alert(test.childNodes[1].nodeType);
IE 下弹出 3,难道 i
标签后面的空文本也算进去了
IE 不是会忽略空文本节点的吗?i
标签前面的空文本就没算进去啊!
但是吧 i
标签换成其他的 div
, p
标签之类就正常的,
但是 i
标签,em
标签,b
标签之类的改变字体样式的标签就会出现这个问题,
这是为什么呢,左右不对称啊
W3Help处有详细的实验过程。
要注意到,IE下,会影响到渲染的空文本节点都没有忽略,比如说,行内标签之间的空白节点。在W3C标准中,行内标签之间的空白节点,必须根据white-space属性进行判断,影响渲染。
下面详细解释会影响到渲染的空文本节点。让我们从空白符开始吧。
W3C 9.1 White space 规定了以下字符为空白符:
 
	

​

和

在接下来的 W3C 16.6.1 The 'white-space' processing model 里讲到空白符是如何参与渲染策略的:
下面是我对标准的翻译
对于每个inline元素(包括匿名的inline元素),下列步骤被执行:
white-space
设为normal
,nowrap
或pre-line
,U+000A
(linefeed)周边的U+0009
(tab)、U+000D
(carriage return)、U+0020
(space)被舍弃white-space
被设为pre
或pre-wrap
,任何不被元素边界破坏的空格序列U+0020
被当做不折行的空格。然而,对于pre-wrap
属性来说,在空格序列末尾有可能出现折行white-space
设为normal
或nowrap
,在不一样的UA相关的上下文中,linefeed字符可能被当做空白符中的任意一个,或者没有字符(因此而不被渲染)white-space
设为normal
,nowrap
或pre-line
,tab字符被转化为空格;同时任何空白符之后的空白符——甚至是inline元素之前的white-space
,只要该white space被应用了white-space:normal | nowrap | pre-line
——会被移除然后内联元素被排版下来,根据bidi信息被重新排序,然后按照
white-space
属性被包裹(wrap,可以理解为放进块级元素内部)起来。包裹过程中,按照white-space
属性考虑是否折行。每行的排版过程中:
white-space
设为normal
,nowrap
或pre-line
,行首的空格被舍弃white-space
设为normal
,nowrap
或pre-line
,行尾的空格被舍弃white-space
设为pre-wrap
,行尾的空格和tab可能被UA折叠浮动定位和绝对定位元素没有新的折行可能。
IE对空白符的解析,正好避免了可能影响到渲染的部分,去掉的空白符是空格在渲染环节被舍弃的部分(非全部,比如行末空白符就被保留了)。
两个过程本不应该混淆:决定空白符是否出现在DOM树中的这一步,发生在构建DOM树的阶段;决定空白符是否被渲染的这一步,发生在构建Rendering树阶段。
这个bug的影响,在于DOM而非CSS,具体而言,遍历childNodes时会有浏览器差异,做额外的判断即可。对于渲染没有区别。
P.S. M$的C++程序员对性能的焦渴导致他们在HTML parse阶段也有意识地控制DOM树大小?