打印

RD3029: IE6 IE7 IE8(Q) 中空的非替换行内元素渲染方式存在差异

作者:钱宝坤

标准参考

非替换行内元素的高度由 'line-height' 特性值决定,'margin'、'padding'、'border' 都不加入行内框高度的计算 (也不参加线框高度的计算),但是他们还是在行内框周围得到渲染。

具体描述请参考 CSS 2.1 规范的 10.8.1 Leading and half-leading

行内非替换元素的宽度不由 'width' 属性决定,他的实际宽度由其中的内容具体宽度决定,如果为空元素,那么宽度的计算值自然也就是 0。

具体描述请参考 CSS 2.1 规范的 10.2 Content width: the 'width' property

根据标准文档描述可以断定,如果空的行内非替换元素存在 'margin'、'padding'、'border' 值,不管实际宽度是否为 0,他都应被渲染出来。

问题描述

当页面中存在一个空的非替换行内元素时,如果给这个元素设置了边框或者背景样式,那么在 IE6 IE7 IE8(Q) 中这些样式将无法显示出来。

造成的影响

有可能造成局部布局效果不尽人意。

受影响的浏览器

IE6 IE7 IE8(Q)  

问题分析

这个问题发生在普通非替换行内元素上,根据 HTML 4.0 规范定义,一般常用的此类元素有:A,ABBR1,ACRONYM,B,BDO,BIG,CITE,CODE,DEL,DFN,EM,FONT,I,INS,KBD,LABEL,Q,S,SAMP,SMALL,SPAN,STRIKE,STRONG,SUB,SUP,TT,U,VAR 等。

【注】:ABBR 元素在 IE6 浏览器中存在脚本处理问题可参考文章 BT9023: IE6 中对 ABBR 元素的相关实现有误 ,本文中将不把此元素列为测试范畴。

以下代码将通过脚本程序构建三组行内非替换元素,并通过样式表让他们都拥有了 'border'、'padding'、'background' 等特性。其中,第一组是空标记形式;第二组是非空标记形式;第三组是触发了 IE hasLayout 特性的空标记形式。

他们都被绑定了 click 事件,以便在样式不显示时,可以通过点击节点来证明他们的盒模型已经被渲染,以及只是显示样式没有被渲染。另外,可以根据 CSS 2.1 规范描述得知,这三组元素的框以及背景都应该给被渲染出来。

<style>
                a,acronym,b,bdo,big,cite,code,del,dfn,em,font,i,ins,kbd,label,q,s,samp,small,span,strike,strong,sub,sup,tt,u,var {font-size:30px; line-height:50px; border:10px solid gold; padding:10px; background:yellow url(w3c.gif); cursor:pointer;} div.info{font-size:12px; line-height:18px; color:#060; background:#EEE;margin:30px 0 30px 0;} </style> <script> var inlineElements = { 'a':'<a></a>', 'acronym':'<acronym></acronym>', 'b':'<b></b>', 'bdo':'<bdo></bdo>', 'big':'<big></big>', 'cite':'<cite></cite>', 'code':'<code></code>', 'del':'<del></del>', 'dfn':'<dfn></dfn>', 'em':'<em></em>', 'font':'<font></font>', 'i':'<i></i>', 'ins':'<ins></ins>', 'kbd':'<kbd></kbd>', 'label':'<label></label>', 'q':'<q></q>', 's':'<s></s>', 'samp':'<samp></samp>', 'small':'<small></small>', 'span':'<span></span>', 'strike':'<strike></strike>', 'strong':'<strong></strong>', 'sub':'<sub></sub>', 'sup':'<sup></sup>', 'tt':'<tt></tt>', 'u':'<u></u>', 'var':'<var></var>' } function getElementSize(element){ return {w:element.offsetWidth,h:element.offsetHeight}; } function getStyle(element,styleName){ return (element.currentStyle) ? element.currentStyle[styleName.replace(/-[a-z]/g, function() { return arguments[0].charAt(1).toUpperCase(); })] : (document.defaultView && document.defaultView.getComputedStyle) ? document.defaultView.getComputedStyle(element, null).getPropertyValue(styleName) : null ; } function bindEvent(element,eventName,fn){ element["on"+eventName] = fn; } function buildElementInfo(tagName,element){ var elementSize = getElementSize(element); document.writeln('<div class="info">'); document.writeln(tagName,' 标记的宽为:',elementSize.w,'px; ','标记的高为:',elementSize.w,'px; ', 'display 值为:', getStyle(element,'display')); document.writeln("</div>"); } function buildElement(title,type,html){ var elementSize,element; document.write(title); for (var i in inlineElements) { document.writeln('<div>'); document.write(i," Tag:"); document.write(inlineElements[i]); document.writeln("其他文本内容……"); document.writeln('</div>'); element = document.getElementsByTagName(i)[type]; (type==2) && (element.style.zoom = "1"); element.innerHTML = html; buildElementInfo(i,element); bindEvent(element,"click",(function(i){return function(){alert(i+" 标记被点击")}})(i)) } } buildElement("<h2>空非替换行内元素渲染情况</h2>",0,""); buildElement("<h2>非空的非替换行内元素渲染情况</h2>",1,"hello"); buildElement("<h2>触发了 IE6 IE7 IE8(Q) 中 hasLayout 特性的空非替换行内元素渲染情况</h2>",2,""); </script>

各浏览器运行结果如下:

  IE6 IE7 IE8(Q) IE8(S) Firefox Opera Chrome Safari
空的非替换行内元素渲染情况
边框是否被渲染
背景色是否被渲染
背景图是否被渲染
是否可被点击
非空的非替换行内元素渲染情况
边框是否被渲染
背景色是否被渲染
背景图是否被渲染
是否可被点击
触发了 hasLayout 特性的空的非替换行内元素渲染情况
边框是否被渲染
背景色是否被渲染
背景图是否被渲染
是否可被点击

根据实际运行结果汇总表可以看出:

  • IE6 IE7 IE8(Q) 中:
    • 空的非替换行内元素的边框和背景没有被渲染,虽然此时已经不能通过脚本取得他们的具体宽高,但是由 'padding'、'border' 特性够成的盒模型渲染占位依然存在,元素可以具有视觉占位空间并且可以被点击到。
    • 非空的非替换行内元素以及触发了 IE 专有 hasLayout 特性的 非替换行内元素以则无此问题,均渲染正常。
    • 从 IE 浏览器的发展历史来推断,最初版本的 IE6 渲染引擎编写时还处于 CSS 1.0 规范执行时期,然而在 CSS 1.0 规范的 4.4 The height of lines 节内并没有明确说明 'margin'、'padding'、'border' 等特性是否还在行内框周围得到渲染。 因此,这很可能是造成 IE6 出现此问题的根源,之后的 IE7 版本依然疏忽了此问题的存在,直至 IE8(S) 以后才被修复。
  • IE8(S) Firefox Chrome Safar Opera 中,不管元素是否为空都可以正常渲染边框和背景。

解决方案

应尽量避免使用的空的非替换行内元素,以及避免为空元素添加显示用样式。

参见

知识库

相关问题

测试环境

操作系统版本: Windows 7 Ultimate build 7600
浏览器版本: IE6
IE7
IE8
Firefox 3.6.10
Chrome 7.0.544.0 dev
Safari 5.0.2
Opera 10.62
测试页面: ie_empty_inline_element_render.html
本文更新时间: 2010-10-25

关键字

IE inline non-replace inline element border background hasLayout 空非替换行内元素 渲染