现在,最令网页设计者头痛的问题就是网页在各个浏览器中的兼容性。而兼容性差最长见的,也是最令人恐惧的便是页面布局混乱。常常一个页面在 IE6下显示的非常完美,而到了IE7(或者FireFox)中,则惨的不堪入目。到底是什么让这些页面那么的水土不服呢?
其实,这些都是IE6酿下的恶果,IE6对web标准的支持过于不足,甚至理解的有偏差,才导致了这些页面的脆弱。而IE7则修正了很多的那种 IE6对css解释和渲染的bug。这种bug有很多。今天,这里只讲其中一个,但是确是最重要的一个,很多的十分混乱的页面都是它造成的。可以不客气地说,它简直就像页面布局混乱黑帮的幕后黑手,是引起页面布局混乱的祸首之一,而且是最大的一个。它就是潜伏在网页背后的‘overflow:visible’IE6渲染bug。不堪入目的网页截图
如果只是简单的说‘overflow:visible’IE6渲染bug,你可能完全没有印象。但是看看下面的这些不堪入目的网页截图,便能引起你心中那无限的伤感
图:这是在IE6中显示的效果截图,十分完美(点击查看完整大图)
这是在IE7中显示的不堪入目的效果截图(点击查看完整大图)上面的两张截图,是我2007年在高达软件公司的真实项目截图。可以看出,在IE7下的显示已经严重变形,虽然不影响软件的功能使用,但是已经严重的影响了用户的使用体验(没有人喜欢拖动横向滚动条)。
再看看下面的这个网页截图,它是我们今天将要使用的例子(源代码在下方有提供),是一个标准的上左右下带侧边栏的虚拟网页。
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/linux/)
图:这是在IE6中显示的效果截图,还算整齐(点击查看完整大图)而当你展开下面这个折叠区域,去看这个页面在IE7下显示的效果图的时候,可能便会大吃一惊了。
图:这是在IE7中显示的效果截图,已经不堪入目了(点击查看完整大图)我们惊讶的看到,网页头部变矮了,最后两句重要的句子消失了;侧边栏变窄了,那个重要的网址的后半部消失了(其实是被右面绿色的区域遮盖住了);而最令人沮丧的是,右面缺了个大口子。原本整齐的布局,已经完全消失,出现的是一个一塌糊涂的页面。
到底是什么,将一个原本好好的页面糟蹋成这样?且看下面的详细讲解
[next]
补充资料:虚拟测试页面在FireFox中的显示结果。初学者不建议阅读(请直接转至第三页学习)
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/linux/)
图:这是在FireFox中显示的效果截图,已经乱的令人抓狂了(点击查看完整大图)为什么在FireFox又有这么令人抓狂的显示呢?原来,这便是IE7的web标准之道的精髓了。随着web标准的推广和认可度的提高,IE7必须向web标准靠拢,但是有必须兼顾到,那些现在在IE6中还显示正常的亿万个已经存在的页面。这样矛盾就产生了遵循标准就意味着页面会显示的乱七八糟,甚至无法浏览;但是如果太过于兼容IE6的那些烂摊子网页,又必然会离web标准越来越远。于是 IE7走出了自己的web标准之道绝对重视web标准,又稍微兼顾IE6的烂摊子。于是,IE7显示的那个页面虽然已经乱了,但是还不像在 FireFox中显示的那样令人抓狂。
附:测试页面在Opera(版本9.25)中的显示效果截图(写文章的时候Opera正好有了新的升级版本)
图:这是在Opera中显示的效果截图,乱的程度和FireFox是一样的(点击查看完整大图)[next]
非也,非也
千万别用IE7,IE7太垃圾了,浏览页面会出现布局混乱,一些在IE6中显示好好的页面,用IE7浏览布局就会混乱。这种言论在网上会经常见到,好像是IE7才导致了那些页面的混乱。其实,非也,非也。
悟空说:师父快快回避,且待我一棒打死这妖精!
八戒说:师父,那个姑娘俊俏的很,怎么会是妖怪呢?大师兄他骗人的!
唐僧说:那位施主,只是一平常人家的姑娘,定然不会是什么妖魔鬼怪。悟空你休得胡言论语。
白骨精说:ohYeah!2比1,看来这下安全了!
那些IE7浏览时会出现布局混乱的页面,就如同利用妖术变了身的白骨精一样,在八戒和唐僧的凡眼看来就是个俊俏的姑娘。但是,在猴哥的火眼金睛下便立刻现了形。而那些布局和样式隐藏着bug的页面,在IE6的袒护和包庇下,化身成完美页面,招摇过市。但是在IE7的严厉的审核下,自然原形毕露、bug层出,从而导致布局混乱。但是,令人遗憾的却是IE7被那些不知情的凡骨俗胎的人们咒骂、贬低、踩在脚底这是一出悲剧!
表面原因放纵的孩子和严厉的父亲
在2007年5月份的时候,我曾经写过一篇文章,叫做《IE6与IE7,放纵的孩子与严厉的父亲》。当时技术水平和对web标准的认知有限,所以写出来的这篇文章,虽然从表面合理的解释了造成布局混乱的原因,但是并没有说到根本上去。可谓只知其一,不知其二,但是这里依然推荐你阅读一篇。因为先知其一,再知其二将更有助于这其二的原因。
其二原因IE6对overflow:visible的误解
为了兼顾到对overflow可能还不是很了解到朋友,这里是关于overflow样式的一些资料:W3C关于overflow的资料。请注意W3C对于visible参数的解释
Visible: "This value indicates that content is not clipped, i.e.,it may be rendered outside the block box(注:后面这句可能是后续版本补充上来的)".
注意,w3c只是说,超出容器的内部不会被剪切。但是它并没有说,超出来的内容可以撑开容器。所以下面这个例子中IE7和FireFox的解释和渲染是正确的,而IE6则是错误的(因为它错误的认为,只有让容器内的内容撑开容器,才能让容器内的内容在超出时不被剪切)。
<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<html xmlns="http://www.w3.org/1999/xhtml"
<head
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
<meta name="Keywords" content="YES!B/S!,web标准,杨正祎,博客园,实例代码" /
<meta name="Description" content="这是一个简单YES!B/S!文章示例页面,来自杨正祎的博客,http://justinyoung.cnblogs.com/" /
<titleYES!B/S!文章示例页面</title
<style type="text/css"
#div1{
border:1px solid red;
width:50px;
}
</style
</head
<body
<div id="div1"
alonglonglonglonglonglonglonglonglongword from <a href="http://justinyoung.cnblogs.com/" _fcksavedurl=""http://justinyoung.cnblogs.com/"" title=""http://justinyoung.cnblogs.com/</a
</div
</body
</html 下面是上面示例分别在IE6,IE7,FireFox(版本2.0.0,12)和Oepra(版本9.25)中的显示效果截图(IE6和IE7共存的方法,可以参考文章《IE6和IE7共存方法(别人是别人的,我是我的)》)。
显然只有IE6的渲染结果是另类的从图片中我们可以看到IE7和FireFox的渲染结果是一样,IE6是个坏孩子,就不多说了,而Oepra的渲染结果和FireFox以及IE7也是有点差距的。但是这不是因为对overflow样式的理解有误差造成的,所以这里也不再扯开话题了。
何以称之为祸首
这篇文章的题目中,将这个bug称之为引起页面布局混乱的祸首。能被称之为祸首,自然有其强悍的地方。那它到底强悍在什么地方呢?其实,很简单,就3条
1. 无论是宽度的内容过长,还是高度的内容过长,都会引发此bug。
2. 无论是文字、图片,还是任意有宽度和高度概念的可见元素,它们的过宽和过高都会引发此bug。
3. 任意有宽度和高度概念的可见元素,它们在默认状态下的overflow样式的值都是Visible(即使你没有设置这个样式)。
补充资料:利用IE Developer Toolbar得到元素样式的默认值
有些朋友可能会问,你怎么知道任意有宽度和高度概念的可见元素,它们在默认状态下的overflow样式的值都是Visible的呢?
其实方法很简单,利用IE Developer Toolbar这个工具就可以知道了。下面的文章和截图,可能会对你有帮助
文章: 《介绍两个,b/s开发中我常用到的小工具》
截图:
图:利用IE Developer Toolbar得到元素样式的默认值[next]
如何修复bug
其实这个bug,我们还是有办法修复的,但都不是很完美的解决方案,想要取得较好的效果,还需要一些技巧。下面便是我工作中总结的一套解决方案。小弟才疏,众多不对之处,还请各位高手指教。
修正这个bug首先要洗脑一下,因为错误的认识将不利于你对解决方法的理解。
1. 虽然,那个虚拟的示例网页在IE6中能够完美的 显示,但是它并不是正确的。我们不能通过css hack的方法让它在FireFox和IE7中显示靠近IE6,而是应该拔下IE6的那层虚假的皮,重新塑造网页,从而让它在IE6、IE7 和FireFox中都能正常显示。
2. 就算让网页在IE6、IE7和FireFox中,都可以正常显示了,但却未必就是最终想要的效果。
3. 为了达到最终想要的结果,可能需要使用不推荐使用的措施css hack。
如何解决横向撑开问题
用word-wrap: break-word解决
导致布局混乱的主要原因,是IE6对overflow的visible的错误解释,才导致宽度被撑开才造成的。所以,我们必须采取措施,让 IE6中容器不能那么放纵孩子才可以。方法就是使用word-wrap: break-word样式(IE特有,FireFox不起任何作用),强制要求容器内的内容不允许撑开父容器。下面的示例可能有助于理解。
<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<html xmlns="http://www.w3.org/1999/xhtml"
<head
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
<meta name="Keywords" content="YES!B/S!,web标准,杨正祎,博客园,实例代码" /
<meta name="Description" content="这是一个简单YES!B/S!文章示例页面,来自杨正祎的博客,http://justinyoung.cnblogs.com/" /
<titleYES!B/S!文章示例页面</title
<style type="text/css"
#div1{
border:1px solid red;
width:50px;
word-wrap: break-word;
}
</style
</head
<body
<div id="div1"
alonglonglonglonglonglonglonglonglongword from <a href="http://justinyoung.cnblogs.com/" title=""http://justinyoung.cnblogs.com/</a
</div
</body
</html 利用word-wrap: break-word可以让IE6中的孩子乖乖的待在父亲的允许访问内。如下图所示
利用word-wrap: break-word后,即使在IE6中,容器也不再被撑开用overflow: hidden解决
显然,用word-wrap: break-word又导致了IE(IE6和IE7)和FireFox的显示结果新的不一致。那还有没有其他的办法呢?擒贼先擒王,既然是 overflow: visible导致的bug,那直接改变overflow的值不就可以了吗?所以,使用overflow: hidden便能让IE6、IE7和FireFox显示一直。下面的这个示例,可能会有助于你的理解
<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<html xmlns="http://www.w3.org/1999/xhtml"
<head
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
<meta name="Keywords" content="YES!B/S!,web标准,杨正祎,博客园,实例代码" /
<meta name="Description" content="这是一个简单YES!B/S!文章示例页面,来自杨正祎的博客,http://justinyoung.cnblogs.com/" /
<titleYES!B/S!文章示例页面</title
<style type="text/css"
#div1{
border:1px solid red;
width:50px;
overflow: hidden;
}
</style
</head
<body
<div id="div1"
alonglonglonglonglonglonglonglonglongword from <a href="http://justinyoung.cnblogs.com/" title=""http://justinyoung.cnblogs.com/</a
</div
</body
</html 下面是在IE6、IE7和FireFox中的现实效果截图。
在IE6、IE7和FireFox中终于显示一致了[next]
一个大问题与残缺的美丽
从截图看,网页在IE6、IE7和FireFox中的确显示一致了(就布局显示而言)。但是,却发现了一个大问题!那就是这并不是我想要的结果呀。假使这里的div是一个侧边栏,我们只是要求,它老老实实的那么宽,不要乱撑宽度就可以了,内容我们还是要看的呀,你不能把内容都剪切了不让我看呀。
如何让很长度文字换行显示呢?其实在前面我们已经使用到了,那就是word-wrap: break-word。虽然它是IE的特有样式,但是足以先解决IE6和IE7中的问题。但是FireFox中没有这个样式,那FireFox下如何使 很长文字自动换行显示呢?我们遗憾的发现FireFox并没有提供类似的样式供我们使用,目前唯一的解决方案是利用JavaScript实现。原理很简单,就是根据宽度,将文本截取成多段,在每段后面强制加上换行符。下面的实现示例可能会有助于你的理解
<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<html xmlns="http://www.w3.org/1999/xhtml"
<head
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
<meta name="Keywords" content="YES!B/S!,web标准,杨正祎,博客园,实例代码" /
<meta name="Description" content="这是一个简单YES!B/S!文章示例页面,来自杨正祎的博客,http://justinyoung.cnblogs.com/" /
<titleYES!B/S!文章示例页面</title
<style type="text/css"
#div1{
border:1px solid red;
width:50px;
word-wrap: break-word;
}
</style
</head
<body
<div id="div1"
alonglonglonglonglonglonglonglonglongword from http://justinyoung.cnblogs.com/
</div
<script type="text/javascript"
// <![CDATA[
if(document.getElementById && !document.all) wordWarp4ff(6)/*数值6根据宽度需要发生变化*/
function wordWarp4ff(intLen){
var obj=document.getElementById("div1");
var strContent=obj.innerHTML;
var strTemp="";
while(strContent.lengthintLen){
strTemp+=strContent.substr(0,intLen)+" ";
strContent=strContent.substr(intLen,strContent.length);
}
strTemp+=" "+strContent;
obj.innerHTML=strTemp;
}
// ]]
</script
</body
</html 看着下面的截图,终于能即满足要求,又在IE6、IE7和FireFox中显示一致了!
终于能即满足要求,又在IE6、IE7和FireFox中显示一致了但是,如同残缺的美丽,惊艳的美隐藏着巨大的缺憾。令人遗憾是如果容器中的内容,不是文字,而是图片时,这种方法将无能为力。只能将容器放宽,或者缩小图片,当然,你也可以使用overflow: hidden将超出的内容剪切掉。另一个遗憾是在FireFox中,div1容器里面的标签和样式也将失去,只留下文本
[next]
另一个焦油坑纵向撑开
上面解决方法,只是横向的、宽度的问题,其实‘overflow:visible’IE6渲染bug,同样也会引起纵向的、高度方面的页面布局混乱。解决纵向撑开bug和解决横向撑开bug需要采用完全不同的解决方案。但是,相比纵向撑开bug解决方案,横向撑开bug解决方案却简单很多只要我们让IE7和FireFox,也能像IE6中那样根据内容,自适应高度即可。如何才能让容器在IE7和FireFox中能够自适应高度呢?其实很简单,也是IE7的重要改进之一,使用min-height样式。虽然IE7中已经支持min-height/min- width和"max-height/max-width"样式。但是IE6却不认识这些"min-"、"max-"开头的样式,所以,我们还需要使用一个css hack为IE6设置一个height,只让IE6认识,IE7和FireFox都不认识。通过这篇文章 《实例讲解符合中国特色的和网络现状的实用CSS Hack(附源码)》 便可以找到应该使用的css hack。下面的示例可能会有助于你理解此解决方法
<!DOCTYPE html public "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
<html xmlns="http://www.w3.org/1999/xhtml"
<head
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /
<meta name="Keywords" content="YES!B/S!,web标准,杨正祎,博客园,实例代码" /
<meta name="Description" content="这是一个简单YES!B/S!文章示例页面,来自杨正祎的博客,http://justinyoung.cnblogs.com/" /
<titleYES!B/S!文章示例页面</title
<style
* { margin: 0; padding: 0; }
#header {
width: 600px;
/*height:50px;注释掉下面两句,放出这一句,在FireFox和IE7中便能呈现bug*/
min-height:50px;/*只设置最小高度,让IE7和FireFox自适应高度*/
_height: 50px;/*采用只有IE6才认识到css hack,让不认识min-height的IE6也有很好的兼容性。*/
background-color: red;
margin:0 auto;/*居中显示*/
}
#body{
width:600px;
margin:0 auto;/*居中显示*/
background-color:blue;
}
#footer{
width:600px;
margin:0 auto;
background-color:#666;
clear:both;/*clear:both,让footer在新的一行显示,很多朋友对clear理解的不够透彻,我以后会特意出篇文章介绍这个样式,有兴趣的朋友可以关注我的博客http://justinyoung.cnblogs.com*/
}
</style
</head
<body
<div id="header"
这里是头部的内容。<br/
可能有网站标题,就像<a target="_blank" href="" title=""博客园</a博客的标题、副标题。<br/
也可能有导航栏在这里<br/
<strong注意这句话在IE7中的显示1</strong<br/
<strong注意这句话在IE7中的显示2</strong<br/
</div
<div id="body"
这里是主体的内容,随便你写啦。我就写上我的博客地址吧<a target="_blank" href="http://justinyoung.cnblogs.com/" title="IE7的web标准之道"YES!B/S!</a
<p 专注于B/S模式的项目。姓名:杨正祎(Justin Young),程序员,专注于B/S模式的项目开发,擅长于Web标准页面设计。</p
<p欢迎你们来为我的博客做客哦,里面有很多关于web标准方面的文章哦。请你们多多指教。</p
<p最后还要非常华丽的署名杨正祎</p
<p日期当然也不能少啦2008-2-21</p
</div<!--end: body --
<div id="footer"
这里是footer,就放一些版权信息吧。©<a target="_blank" href="http://justinyoung.cnblogs.com/" title="IE7的web标准之道"YES!B/S!</a
</div<!--end: footer --
</body
</html 下面是修正后页面的效果截图,在IE6、IE7和FireFox总都是令人满意的显示结果。
利用min-height和css hack让容器在IE7和FireFox中自适应高度(点击查看完整大图)后记
对于最容易引起网页布局混乱的‘overflow:visible’IE6渲染bug,上面从多个方向和角度进行了讲解。虽然有些方面还不能有完美的解决方案,但是在更理性的解决方案出现之前,暂时也是没有办法的事情,只能留个遗憾在那里,因为我们还要继续前进