内联排列的间距 和 浏览器对换行符理解成文本节点的原因研究

来源:互联网 发布:2017中国云计算500强 编辑:程序博客网 时间:2024/06/05 02:57

内联排列的间距 原因研究

 

下面的代码,我使用了列表li(display:list-item),其结果是所有浏览器下 li 之间都有间距

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>标签间换行测试</title><style>*{margin:0;padding:0;}body{margin:10px 10%;background:#666;}ul,li{list-style-type:none;}li{display:inline;background:#CCC;}</style></head><body><ul><li>test</li><li>test</li><li>test</li></ul></body></html>

 

在IE6 IE7 浏览器上的效果如下,背景色块之间没有间距,但文字间有

IE8 Chrome  Firefox Opera Safari 浏览器下在都有一段间距

 

下面的代码,我使用了内联元素span(display:inline),其结果是在所有浏览器下都有间距

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>标签间换行测试</title><style>*{margin:0;padding:0;}body{margin:10px 10%;background:#666;}span{background:#CCC;}</style></head><body><div><span>test</span><span>test</span><span>test</span></div></body></html>

 

下面的代码,我使用了块元素div(display:block),其结果是在IE IE7下没有间距,剩余其他所有浏览器下都有间距

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>标签间换行测试</title><style>*{margin:0;padding:0;}body{margin:10px 10%;background:#666;}div{display:inline;background:#CCC;}</style></head><body><div><div>test</div><div>test</div><div>test</div></div></body></html>

 

事实上,只要在 使用display:inline横向排列的非浮动元素间 拍了换行符,IE6 7 8 firefox safari opera chrome 等都会有间距,只不过表现不一致罢了


解决办法:

1、如果是块元素,给其设置的 display:inline 换成 float:left 就可以解决问题。块元素设置内联可以排成一排,当然设置成浮动也可以做到,并且浮动的好处在于可以消除标签之间的间距,但是由于IE6 双倍水平外边距BUG,我们最好既设置 float:left 同时也设置 display:inline,这样就可以达到一举两得的效果,既没有IE6双倍水平外边距,标签之间也没有间距,所以如果以后给 块元素设置行内排列,最好是把 float:left 和 display:inline 一起使用;

2、还有个办法就是标签之间不要换行,连着书写,这样就没有换行符也就没有间距了,比如 <ul><li>test</li><li>test</li><li>test</li></ul>;

3、如果你觉得这样书写太长,不便于阅读,我们可以在 闭合标签的“>” 之前换行,因为它不在标签之间换行,这样的换行符不会造成标签间的空白间隙(下面有示例);

4、如果是内联元素,给其设置 float:left 即可解决问题,内联元素默认display就是inline,所以无需再设置,而且内联元素也不会出现IE6双倍水平外边距。当然,2、3方法也同样适用。

总结一下:

只要是设置display:inline以内联形式排列的元素(或者自身就是内联元素),标签之间换行就一定会出现间距,要想清除间距就得用以上办法解决。

 

 

那么这个间距和浏览器是否把换行符当成文本节点有没有关系呢?答案是没有,因为我测试发现,IE在没有把换行符当文本节点的情况下,也依然是有间距的。  

 

给上面第一个代码body闭合标签前,加上下面的代码(分别在各个浏览器平台运行一下)

<script>var lis = document.getElementsByTagName("ul")[0];alert(lis.childNodes.length);</script>

我们可以看出IE6 IE7 IE8会忽略所有的换行符,只有3个子节点,就是li元素节点

而其他例如firefox之类的浏览器会把换行符当文本节点,所以会有7个子节点,另外4个是空白的文本节点

我把标签之间不换行,我在闭合标签内换行,看看有什么不同,下面是测试代码

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>闭合标签内换行测试</title><style>*{margin:0;padding:0;}body{margin:10px 10%;background:#666;}ul,li{list-style-type:none;}li{display:inline;background:#CCC;}</style></head><body><ul><li>test</li><li>test</li><li>test</li></ul><script>var lis = document.getElementsByTagName("ul")[0];alert(lis.childNodes.length);</script></body></html>

我们可以看出IE6 IE7 IE8依然会忽略所有的换行符只有3个子节点,就是3个li元素节点,而其他例如firefox之类的浏览器也还是会把换行符当文本节点,但是只有5个子节点,另外2个是空白的文本节点,就是闭合标签内的换行符。但是由于是标签名内的换行,并非标签之间的换行,所以并不会造成标签之间的间距。

 

总结一下各个浏览器对标签间换行符的表现:

IE6 IE7 IE8都会忽略换行符,不会认为是一个文本节点,但是这不会影响IE系列浏览器把标签间的换行符留出间距;

其他的浏览器不仅把标签间的换行符当成文本节点,并且还在标签之间留出间距;

所以我们最终得出有2种换行情况:

第一种就是我最上面贴的 标签之间直接换行 的代码,标签间直接换行,这在IE6 IE7下的表现(3个LI背景色连成一片点击查看)和IE8下略有不同(3个LI背景色没有连起来点击查看),但实际上IE 6 7 8都是有间距的,只不过表现上略有差别。

第二种就是我上面贴的 闭合标签名内换行 的代码,这种情况在任何浏览器上看都是没有间距的,无论是文字间还是背景色之间,它的效果与标签之间不换行连写是一模一样的效果,但是这样书写又可以达到标签间换行带来的视觉上的整齐易读,是一个比较好的方法。

 


浏览器对换行符理解成文本节点的原因研究

关于浏览器和空白节点的问题,大家继续看我下面内容前,可以先看看这个文章 因浏览器而异的空白节点

 

经过下面一段代码的测试,我发现了一些问题,最终对这些有了一些理解,和大家分享一下

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>CSS DOM均无法改变浏览器对元素display属性的理解</title><style>span{display:block;}</style></head><body><ul><li>test</li><li>test</li></ul><div><span>test</span><span>test</span></div><input type="button" onClick="test();" name="test" value="test" /><script>function test(){var lis = document.getElementsByTagName("ul")[0];alert(lis.childNodes.length);var nowspan = document.getElementsByTagName("span");for(var i=0;i<nowspan.length;i++){nowspan[i].style.display = "block";}var spans = document.getElementsByTagName("div")[0];alert(spans.childNodes.length);}</script></body></html>

 

li测试的话,IE系列都不会把换行符当成空白文本节点,但是如果用span测试,IE会把第一个标签间的换行符忽略,之后的标签间换行符都认为是文本节点。。。

原来IE虽然会忽略标签间的换行符,但是也是分情况,如果标签的框类型是block或者item-list,那么之间的换行符IE会忽略,但如果是inline则不会忽略。

具体每个display的属性大家可以查阅 W3C的 HTML DOM Style 对象的 display 属性 ,通过查阅手册我们会发现哪些属性让元素前后默认自带换行符的(list-item手册中没说明,但是我认为它默认前后是有换行符的,因为实质上它是块框)。

因为W3C的HTML DOM手册中没有说明list-item前后是否有换行符,由此引出一些其他内容

display block | none | inline | list-item

  • block:显示块对象。此元素前后会带有换行符。
  • none:隐藏对象,且不为对象保留物理空间。
  • inline:默认。此元素会被显示为内联元素,元素前后没有换行符。
  • list-item:将块对象指定为列表项目。并可以添加可选项目标志。

list-item其实是块元素,再看看关于块元素的讲解

替换元素 超出 CSS 格式器范围的元素。 HTML中的 img, input, textarea, select, object 都是替换元素。 所有的替换元素且仅有替换元素才具有固有尺寸。
块级元素 在视觉上被格式化为块的元素。float元素以及display:block或list-item的元素都是块级元素。
内联元素 不形成新内容块的元素。display:inline的元素都是内联元素。
已定位元素 position属性不等于static的元素。

浮动元素也是块元素,那么看看关于浮动的讲解

浮动元素
float 属性定义元素在哪个方向浮动。以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。

如果浮动非替换元素,则要指定一个明确的宽度;否则,它们会尽可能地窄。

假如在一行之上只有极少的空间可供浮动元素,那么这个元素会跳至下一行,这个过程会持续到某一行拥有足够的空间为止。

看了上面的应该知道list-item其实就是块元素,那么它默认前后也是有换行符的。 

 

另外我还发现通过CSS来改变元素的display属性是没用的,我甚至通过DOM对节点的Style对象的display属性进行修改,设置成inline依然无效,所以这个元素天生该有的display属性是什么,浏览器就做什么样的处理,和css设置无关,后天修改也没用。


 

按我的理解:

1、block和item-list元素默认前后就有换行符,我们手工拍了一个换行符,而HTML会把连续换行符当成是一个换行符(pre标签内的会保留不会合并),既然当成是一个换行符,而IE是对标签自身前后带的换行符自动忽略的,所以我们看到使用 LI 没有把换行符当文本节点。这里我就再提一下刚刚我链接的那个文章因浏览器而异的空白节点,文章里面说IE会忽略换行符造成的空白文本节点,我觉得应该这样说“ IE会忽略元素Style对象display属性前后自带的换行符”,IE的工作原理应该是先判断元素是否默认前后自带换行符,如果是那么就忽略掉,我们手工拍的个换行符被HTML给合并成一个,那么IE自然会把它忽略掉,因为它认为是标签自带的;

2、inline元素默认前后没有换行符,我们手工拍的换行符不是标签自带的,那么IE认为是我们手工添加并需要呈现的,所以它会把换行符当成文本节点;

说到这里就很好理解其他浏览器的表现了,这些浏览器可不管这个换行符是标签前后自带的换行符,还是我们手工按下的换行符,还是合并的,它们一律都当成文本节点;

 

总结一下: 

IE浏览器会忽略元素display属性造成的前后换行符,而 标签间手工拍的换行符 被 标签前后自带换行符 合并,因此被IE忽略掉,IE不会认为这换行符是文本节点,但IE不会忽略内联排列的元素之间手工换行符的间距

其他浏览器则会把换行符当成文本节点(同样是自带换行符和手工换行符合并成一个),同时这些浏览器也不会忽略内联排列的元素之间手工换行符的间距

所有浏览器之间相同的部分就是,它们都不会忽略内联排列的元素之间手工换行符的间距

 

实际运用中:

如果你用内联排列,要消除间距就得设置float,或者把标签都写在一行不要换行,或者在闭合标签内换行 

 

原创粉丝点击