巨文!浏览器自身的BUG —— 不同浏览器在页面缩放状态下的渲染差异分析!让你的网站在iPhone和Android上同样完美!
Posted on 2011-07-25 11:03 随它去吧 阅读(26047) 评论(63) 编辑 收藏 举报过度追求浏览器兼容其实就是拿不同浏览器开发者的个性或Bug惩罚自己!
前言
Web Developers 往往会因为自己的作品无法“完美兼容”多个浏览器而苦恼不已,然后责怪自己水平不够或者MSIE把你惯坏毒害了以至于无法写出“标准的HTML+CSS+JS”!
但事实上,很多所谓的兼容性问题未必都是 Web Developer 自己造成的,也会有浏览器本身的问题!毕竟浏览器开发商也是人,也会犯错误,他们的软件同样会有Bug,唯一不同的是,他们所犯的错误往往会“惩罚”和困扰数以千万计的下游Web开发者!
当然了,话说回来,就算浏览器自己犯了错误,也不能作为 Web Developer 不去考虑兼容性的借口,毕竟你不能告诉网站用户“您眼前的页面显示不完美现象将会在下一版本的Firefox/Opera/Chrome中得到解决,请耐心等待新版本的发布……”,开个玩笑:)
因此研究不同浏览器各自的特点及其所犯错误的表现总是有必要的。
下面说说我怎么会想到研究这个问题的。
目前正在开发的网站产品对用户体验和交互水准要求比较高,网站会用到许多有特色的自定义控件,然后在我对这些控件进行封装(采用 jQuery plugin 的形式)的时候遇到了一系列浏览器兼容方面的问题。
事实上这已经不是单纯的浏览器兼容性问题了,而是浏览器自身对同样的Html+CSS代码渲染时出现了问题(问题看似小问题,但是对实际应用中的用户界面破坏很严重)。具体说就是:
当用户进行页面缩放浏览的时候,即便同一个浏览器软件,在不同缩放比例下渲染出的效果也是不一致的,会出现各种各样的毛病,造成讨厌的视觉效果破坏。
然后为了彻底解决这种类型的问题及其造成的破坏,我不得不从根本上去找原因,找解决方案,于是就有了这篇文章。
一、遇到问题的jQuery插件
上面提到我在开发时遇到问题的 jQuery plugin 之一是一个“庸俗的” Button ,说它庸俗是因为这样的插件目前在 jQuery 的世界里至少已经有数以万计了,但是我却还是没能找到一个真正完美的,或者说能让我满意的,也许骨子里的真正原因是人都更希望使用自己可控制的东西吧。
简单介绍一下这个 Button plugin :为了支持丰富的视觉效果和更容易在页面中进行控制,我采用Div来模拟一个“四态(normal,hover,pressdown,disabled)按钮”,你只需要通过改变CSS,就可以创建出简洁的文本按钮,通过CSS结合使用背景图片更能够模拟出各种独具特色的按钮形态,关于它,后面我会另开文章介绍,这里就不罗嗦了。
严格来说,一个具有通用性的按钮应当采用九宫格的“四角固定,中间区域自动拉伸”模式来进行渲染,这样才能使得按钮可以随意控制高度和宽度,并且在不同尺寸下都能够表现完美,但是 Web 开发有其独特性,我们这个按钮只需要能够满足自动延展宽度就行,故而采用“左中右三段渲染”的方式进行开发。
因此,在这里您只需要记住我们是用3个Div来分别模拟按钮的左中右样式即可。
作为一个按钮,当然不仅仅是模拟一个 Button look Face 那么简单,它还要能够实现形态变化,响应鼠标事件乃至键盘动作,以此来宣示自己的按钮身份并实现相应的功能。然而这些并不是本文的讲述重点,本文只关注外观模拟的部分,完整的 Button Plugin 开发文章,会在今后放出。
二、本文所讨论问题的现实意义
肯定有人会觉得,你非要用 Div 去模拟一个 Button 效果,这分明就是自寻烦恼,你这个例子根本不具有代表性,因此也说明不了什么问题。
真的是这样吗?未必见得吧!就算用 Div 模拟 Button 这件事儿本身是我自己闲的蛋疼,可是我总归是在使用 Html+CSS 去实现一个视觉效果,这一点你无法否认吧。而 CSS 对于网页来讲,其作用无非就是帮助页面排版布局,与Html一起为用户展现出友好优雅的视觉效果而已。那么既然在我实现这个视觉效果的时候遇到了问题,别人在实现其他视觉效果的时候同样也会存在问题,我这里是模拟按钮出问题,别人那里就有可能是页面模块对齐出现错位,影响会更大!这就是本文的现实意义所在!
当然了,也许还有善于抓漏洞的朋友会说“你这个所谓的‘不同缩放比例下的渲染效果差异’只有在用户不断改变网页大小的时候才会出现,事实上又会有多少用户会像你一样闲的蛋疼,逮着一个网页缩来放去呢,因此这点小差别一般用户根本就不会有机会感知的到,你这么斤斤计较又是何苦呢?”
聪明!精彩!貌似合情合理且又丝丝入扣!
然而我的答案是这样的:
1、你所描述的情况基本属实,但是这能够成为浏览器渲染页面可以不严谨的借口吗?难道某些浏览器一方面宣称支持这标准那规范,对“不标准”的微软大加鞭挞,另一方面却又对自己要求降低吗?
我就想问一句:凭什么我写的无错的、且“标准的” CSS 和 HTML ,你们在不同缩放比例下给我渲染出来却不一样?
(抱歉,吐槽到此结束)
2、为了避免有人说我只会讲大道理,给出两个更直观的理由:
- A、现在 iPhone 手机和 Android 智能手机大行其道,对几乎所有网站来讲,使用这类设备上网访问的用户比例已经在不断提升,而且还将持续大幅提升!而目前为止并非所有网站都有能力为用户提供一个移动终端的专用版本(别跟我提 Wap ,玩这种手机的人绝对不会对 Wap 网站感兴趣,因为 Wap 体现不出他们手机的优越性),所以绝大多数这类用户都会用他们的手机浏览器( Safari Mobile 或者 Android 自带的 Webkit 内核的浏览器)来直接访问你的Web网站,而无论 iPhone 还是 Android 上的手机浏览器都有自动缩放页面的功能(当然这是因为手机的屏幕分辨率小),此时缩放后的页面渲染效果就显得至关重要了!比如你网页上一个140像素宽的按钮,经过 iPhone 的缩小适应屏幕宽度之后就只有一点点了,而你想准确的点击操作它的话一般都会进行放大操作,而这时,按钮撕裂了……
- B、台式电脑用户都在大幅提高自己的配置,显示器21寸以下你都不好意思跟人打招呼,23寸才算马马虎虎,分辨率自然是1920*1080了,然而在这种分辨率下看网页的默认字体会有多吃力你想过么?怎么办?放大网页呗,多简单啊,按住Ctrl+鼠标滚轮一滚,哇,放大的文字好牛逼!等等……什么?按钮撕裂了?太尼玛煞风景了!
好了,看完这两条依然认为这个问题没有意义的筒子们,您可以出门右拐了,这篇文章对您没啥用,真的……
三、浏览器测试环境
浏览器兼容性测试是个很讨厌的工作,首先环境搭建就很烦:
我在自己的 Win2003 上面安装了 IE8,Chrome11,Firefox5,Opera11,Safari5,又在虚拟机上安装了 IE6,IE7,然后还可以使用别人 Win7 上的 IE9 ,这样就基本覆盖了 Windows 上面的常用浏览器,也将作为我的测试环境。
对于 Linux 来说,常用浏览器无非也是 Firefox,Opera,Webkit 这三个内核,他们的表现与各自的 Windows 版本相比并不会有本质不同。苹果的 Mac OS 所使用的 Safari 与 Windows 下的 Safari 一样大同小异。因此我就没有单独安装这两个系统进行测试,以后有机会,这一课我会补上的。
当然了,现在这个时代,要测试浏览器兼容性,你还少不了 iPhone ,运行在 iPhone 上面的 Safari Mobile 目前可是相当大的一个访问群体哦,另外还有我的 Android ,除了其自带一个 Google 自己开发的以 Webkit 为内核的浏览器,还有 Firefox 和 Opera 分别为 Android 平台开发了响应版本的浏览器,这次把它们一并纳入测试范围!唯一有点遗憾的是微软的 WP7 ,暂时没有机器可以进行测试,后面我会附上页面源码,希望有条件的筒子帮我测试一下。
总结一下,现在我们有了
IE6/IE7/IE8/IE9/Firefox5/Opera11/Safari5/Chrome11/Safari Mobile/Firefox Mobile/Opera Mobile/Chrome Mobile
作为测试环境!
四、发现和解决问题的详细过程
1、首先用4个Div和纯CSS来模拟一个简单按钮的外形
由于本文旨在分析浏览器页面渲染的差别,故而按钮的状态变化、事件响应等在这里不做实现,这个页面分别采用了float和absolute两种布局对按钮进行了模拟,先看代码:
<!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> <title>Browser Tester</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type="text/css"> *{ margin: 0px; padding: 0px; border: none; } body{ background-color: Purple; padding: 20px; } /*按钮自身的容器*/ .Container{ height: 40px; width: 200px; position: relative; } /*按钮左中右容器基本样式设定*/ .Left{ width: 10px; height: 100%; background-color: Yellow; } .Center{ width: 180px; height: 100%; background-color: Orange; color: White; text-align: Center; font-size: 14px; line-height: 40px; } .Right{ width: 10px; height: 100%; background-color: Yellow; } </style> </head> <body> <div id="floatContainer" class="Container"> <div class="Left" style="float: left;"></div> <div class="Center" style="float: left;">Float方式模拟的按钮</div> <div class="Right" style="float: right;"></div> </div> <br /> <div id="absoluteContainer" class="Container"> <div class="Left" style="position:absolute;left: 0px;"></div> <div class="Right" style="position:absolute;left: 190px;"></div> <div class="Center" style="position:absolute;left: 10px;">Absolute方式模拟的按钮</div> </div> </body> </html>
代码比较简单,注意这里把用来模拟按钮的div基本样式都放在了文档头部的<style>块里面,而具体到两种不同布局方式的差别部分,为了直观起见,我直接写在了标签的style属性里面。下面看效果:
IE6 | |
IE7 | |
IE8 | |
IE9 | |
Firefox | |
Opera | |
Chrome | |
Safari |
|
大家看到了,在各浏览器标准显示比例下解析出来的效果接近一致,非常"完美"!等等,这就行了么?显然不是的,否则就不会有这篇文章存在的价值了。
另外,其实仔细看的话,不同浏览器对页面渲染的区别已经初露端倪,比如:
A、不同浏览器对默认字体的选择是不一样的,有的是宋体,有的是雅黑……好吧好吧,这个可以理解,算我吹毛求疵,我该在CSS指定默认字体的……
B、对line-height的解析和渲染,各浏览器并不一致,有兴趣的可以自己截图对比一下,尤其是IE系列,相比其他浏览器总会有向上偏移,除IE9之外的其他IE版本,通常宋体会上偏2个像素,雅黑会上偏1个像素(所以你知道的,为了美观起见,尽量用雅黑吧)
C、对于<br/>的解析,高度不尽相同,当然这个并不十分影响视觉效果,但是依然体现了各浏览器开发商的“不负责任”,你们整天骂人家微软不遵守标准,你们倒是好好遵守啊。
2、对模拟出的简单按钮效果在不同浏览器下分别进行缩放测试
IE6 |
IE6无整页缩放功能,测试忽略 |
IE7 |
页面在小于(含)50%比例下显示的时候<br />效果消失,两个按钮粘连在一起; 在最小10%的显示比例下文字渲染还超出了按钮边界; 在放大比例的时候对<br />的渲染处理不好,高倍显示下这个换行非常夸张; 除了上述三个小问题外,其他比例均可以算作显示良好。 我的打分:70 |
IE8 |
不过小问题依然存在,那就是在10%比例下,文字出现了换行,虽然无实际意义,也算一点小遗憾吧; 除此之外,可以看到IE8对放大时两个div之间<br />的间隙做了更加人性化的处理,不像IE7那么生硬了。 我的打分:85 |
IE9 |
不知道微软有没有刻意处理这些,但是之前IE7和IE8出现的小问题全部消失了 ! 我的打分:98(留点改进空间给微软吧) |
Firefox |
跟IE9相比,除了缩放倍数受限一点之外,在渲染效果上不相上下,很赞! 我的打分:95(缩放倍数受限扣3分) |
Opera |
其渲染质量与IE9和Firefox不相上下。 我的打分:98(与IE9打平) |
Chrome |
在这12个缩放级别里面总共出现了如下多的问题,让我比较失望: a、50%和57%两个比例下, 文字错行; b、57%,69%,144%,207%四个比例下,Float定位方式Center和Right之间出现了 1像素的缝隙; c、而在248%和298%两个比例下,Float定位方式出现了2像素的缝隙! 不仅如此,连Absolute方式也出现了1像素缝隙! 我的打分:50 |
Safari |
不过Safari毕竟聪明,他把缩放限制为10个级别,甚至你连缩放比例都看不到,囧! 不过借此倒是隐藏了文字折行的bug,只剩下裂缝问题了: a 、第1,第2,第6,第8级别Float方式出现1像素裂缝; b 、第9,第10级别,Float方式的裂缝扩大到2像素,而absolute方式也出现了1像素裂缝! 我的打分:55 |
测试小结:
A、在浏览器渲染能力方面,其实微软一直在进步,他追求的高容错能力的的确确在为用户体验考虑,而这却成了别人攻击他“不标准”的口实!
B、Firefox和Opera这两个有着深厚底蕴的家伙的确手里有真功夫,然而这还只是个开始,更多测试在后边。
C、一直为人所推崇的Webkit其实远没有那么完美,只不过人家抓住了“快”这一噱头和卖点!再加上无论Apple还是Google都是善于宣传推广灌输的高手,所以……
D、从CSS使用角度来讲,Float的布局方式更容易出偏差!如果您为了图文布局方便,尽管大胆的Float就行了,可如果是想实现某些漂亮的视觉效果,那么请三思。
3、纯CSS的渲染已经出现问题,那么如果换成图片模拟按钮呢?
前面用纯CSS模拟的按钮出问题了,很不幸!那么如果我用图片来进行模拟呢?会好一点?或者更糟?让测试结果来证明吧!
下面我写一个新的页面,使用图片来模拟按钮的Normal态(其他三态原理相同),先看看这个背景图片
这是一个png格式的图片,宽6像素,高度105像素,背景透明,按钮实体高度为32px,我在设计的时候是按照35像素做的,原因后面会有解释。
然后修改CSS和网页代码,使之能够模拟一个图片按钮的左中右三段(之所以采用三段的方式来模拟是因为我们封装的按钮是希望宽度不受限制的,因此固定宽度背景图片搞不定),下面是全部代码(听取批评,给body设置了默认字体为雅黑):
<!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> <title>Browser Tester</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type="text/css"> *{ margin: 0px; padding: 0px; border: none; } body{ background-color: Purple; padding: 20px; font-family: "微软雅黑", "宋体"; } /*按钮自身的容器*/ .Container{ height: 32px; width: 200px; position: relative; } /*按钮左中右容器基本样式设定*/ .Left, .Center, .Right{ background-image: url('btn_bg_noShadow.png'); } .Left{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px 0px; } .Center{ width: 188px; height: 100%; background-repeat: repeat-x; color: White; text-align: Center; font-size: 14px; line-height: 32px; background-position: 0px -35px; } .Right{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px -70px; } </style> </head> <body> <div id="floatContainer" class="Container"> <div class="Left" style="float: left;"></div> <div class="Center" style="float: left;">Float方式模拟的按钮</div> <div class="Right" style="float: right;"></div> </div> <br /> <div id="absoluteContainer" class="Container"> <div class="Left" style="position:absolute;left: 0px;"></div> <div class="Right" style="position:absolute;left: 194px;"></div> <div class="Center" style="position:absolute;left: 6px;">Absolute方式模拟的按钮</div> </div> </body> </html>
正常比例状态下的按钮效果图我就不一一截图贴出来了,除了IE6不支持透明png图片有点丑之外都很完美:
说到IE6,我以后开发的Web应用几乎都不再考虑它了,从现在的形势来看,IE6被放弃将是很短时间内的事情,我乐意提前一步。
下面要做的是我不怎么喜欢的,给浏览器挑毛病!看看这个图片按钮在不同浏览器的缩放状态下表现如何?方便起见,我只把出问题的状态贴出来。
其实已经可以隐约预见,前面的测试还只是测试浏览器对纯CSS的解析,渲染对象基本上都是些矢量的线和块,而现在要测试的页面,除了浏览器解析CSS的能力外,还要考验浏览器的位图渲染能力,所以出问题的几率理应更大一些才是。
IE7 |
但是在对图片的渲染上,竟然做得如此完美!不论在任何比例下渲染出的背景图片都非常的精准、流畅和圆润! 我震惊了!
|
IE8 |
虽然可能具体效果小有差别,但是表现形式却是一样的,都是对背景图片渲染出现了偏差造成人的视觉误差。 为了节省大家的时间,请具体参看下面的IE9截图吧 |
IE9 |
仔细观察一下你会发现这种错位其实是对背景图片渲染效果差异造成的视觉错位! 不信我们对上图“偏移”较为严重的70%那张图进行截图和放大来看:
|
Firefox |
面对这个挑战时,Firefox跟IE8和IE9几乎是一样的表现,当然好像相比IE8和IE9略微好一点点。 出现这种“视觉误差”的原因前面已经分析过,截图放大后也得以证实。
|
Opera |
A 、从120%开始,按钮Left与Center中间出现了一条裂缝,这个问题较为严重; B 、放大到一定程度后按钮右侧渲染出现了超限,本来设定为no-repeat的背景被渲染多了一块! 验证后发现,若按钮高度超过背景高度,渲染时按钮下侧同样会有类似的问题! 裂了!它竟然裂了!无法接受呀! |
Chrome |
你裂的惊天动地,裂的无以伦比,裂的花样百出啊!
|
Safari |
显然Safari对图片的渲染要比Chrome更好一些。
|
测试小结:
这次测试估计会刺激到很多人,我就是其中之一!还是总结一下吧:
A 、IE8、IE9相比IE7应该是修改了相当大一部分页面解析引擎,是的,IE终于比较“标准了”,可是你为什么把IE7那完美的背景图片渲染能力也给丢弃了呢?
B 、Firefox在页面缩放时的图片背景渲染也不比现在的IE8和9强多少,距离“最标准最完美的浏览器”还差了很多呢。
C 、最让人大跌眼镜的是Chrome和Safari,号称最快的浏览器,怎么能光顾快而不求质量呢,那千奇百怪的裂缝啊,让人忍无可忍有木有!
D 、Opera整体表现还是很棒的,不过秉承了它一贯的风格,就连犯错也犯的比较另类,一条似有若无的裂缝也就罢了,渲染超界您还是头一份儿。
4、这个页面在智能手机浏览器上究竟表现如何?
您可以理解为我要针对本文第二部分所阐述的现实意义给出例证了!
相信有人在看过我前文对智能手机与网页缩放渲染差别的描述之后,还是没有直观的感受,OK,现在我给来点刺激的,为您奉上两大智能手机,四大智能机浏览器的真实表现!
先来看iPhone的Safari Mobile!
A 、iPhone 竖屏默认比例和放大后的效果对比(两个都裂了):
B 、iPhone横屏默认比例和放大后的比例效果对比(裂的更离谱):
有点无语了吧?是不是对iPhone有点失望?我们再来看看Android下的效果!
A 、Android自带浏览器竖屏默认和放大状态(都不错,很完美)
B 、Android自带浏览器横屏默认和放大状态(依然很完美)
同样是Webkit内核,谷歌在Android内置的这个浏览器表现比他在电脑中的版本可强了太多了!
C 、Android版Firefox竖屏及其放大效果(放大时出现渲染视觉位移,跟电脑版Firefox一个德行)
D 、Android版Firefox横屏及其放大效果(放大时出现渲染视觉位移,跟电脑版Firefox一个德行)
E 、Android版Opera竖屏及其放大效果(放大时出现出现裂缝,跟电脑上一样)
F 、Android版Opera横屏及其放大效果(放大时左边出现裂缝,右侧超限渲染也跟电脑保持了一致)
小结一下:
总结iPhone和Android浏览器的表现,我们发现:
A 、在手机上直接访问web页面的时候,竖屏状态下的默认页面和元素及文字大小,基本不具备可读性,必须要放大!
B 、在横屏状态下默认页面元素及文字大小,勉强可读,但一般人也通常习惯放大阅读,换言之,手机上访问web页面基本都需要放大浏览。
C 、手机版的Safari、Firefox、Opera,基本上保留了其在电脑版上的同样毛病,因此,手机上浏览页面进行放大渲染一般都会出现前文所述的问题!
D 、Android原生自带的浏览器虽然是Webkit内核,但却进行了特殊优化,表现优异!
E 、上述事实再次证明,讨论浏览器缩放渲染页面的效果差异是绝对有其实际意义的!
5、汇总一下,前面测试出现的问题哪些可以接受,哪些必须解决?
个人的意见和想法,不保证100%适用他人:
A 、浏览器小比例的缩小状态(比如50%以下)下出现的渲染异常几乎都可以忽略:一来电脑上的访问可能有略微缩小的需求,但不会缩小太多,二来智能手机浏览器上根本就没有缩小需求(本来已经很小导致几乎无法浏览),这样的话,IE7的小比例渲染粘连和文字超出边界,IE8的小比例渲染文字换行,Chrome小比例状态下的文字折行基本可以忽略了;
B 、由于渲染效果导致的视觉偏差也基本可以忽略,因为这种偏差不会破坏页面元素的整体感,只是让人感觉有些不爽而已,当然了,能找个办法尽量降低这种破坏最好了,至于怎么做我们会在后面分析。这样,IE8/IE9/Firefox出现的渲染偏移问题我们可以暂时无视了。
C 、在Opera身上出现的超界渲染问题,只在很高的放大比例下才能发现,我们姑且对它宽容一些吧!
D 、页面元素之间的裂缝绝对不可以接受!尤其是放大状态下出现的裂缝,更加让人无法容忍!
根据这一要求,电脑上的Opera、Chrome、Safari都是不合格的!手机上的Safari、Opera也同样不合格!我们强烈要求浏览器开发商加以改进!
按照我的判决,IE要去面壁,Firefox必须忏悔,Opera应该去撞墙,Safari可以去死,Chrome直接车裂了吧!
补充一句:该车裂的是电脑上的Chrome,Android上那个谷歌的“私生子”,没敢公开身份和姓名的Chrome却表现完美,不在其列。
6、尝试解决前面测试总结出的问题
问题出现了,总要去解决,抱怨是没用的,等待浏览器自己的改进那更是不靠谱的事情。现在我们已经明确,目标如下:
A 、元素之间的裂缝问题必须解决;
B 、渲染出现的视觉偏差尽量解决;
其中问题A在纯CSS的环境中比较容易解决,给父容器设置一样的背景色就可以掩盖这个小缺憾,但是这个方法在图片模拟按钮的环境下行不通,尤其是背景图有透明区域的情况下,这样的背景叠加会异常丑陋(反而不如没有Left和Right,一通到底的统一背景来的好看),而全部实色背景图片模拟的按钮又有太强的局限性。
问题B有些困难,我们放大观察前面那些出现偏差的截图就会发现,偏差主要出现在Left、Right与Center交界部位的那几个像素上,在本文的实例当中,按钮背景图片宽度是6像素,事实上纯粹属于Left和Right的只有3个像素,其余延伸出的3个像素均与Center的背景完全一致,而正是这左右各延伸出的3个像素与Center背景在渲染时出现了不一致,最终导致视觉误差。
怎么解决?
仔细观察一下,其实所有浏览器在渲染时出现的裂缝没有超过2像素的,那么通过强行对Div定位进行偏移(比如Center向左偏移2个像素,同时宽度增加4像素,从而对Left和Right各覆盖2像素),这种元素叠加的方式能否从视觉上解决这个问题呢?我们来试一下:
下面是修改过的代码(由于两个原因:一是Float定位有更大不确定性,二是absolute定位实现偏移和覆盖更加方便,所以这里只对absolute定位方式进行修改,Float效果留作对比,另外考虑到本例图片Left和Right分别只有3像素是有用的,我就干脆都给他强制偏移3像素看看)
<!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> <title>Browser Tester</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type="text/css"> *{ margin: 0px; padding: 0px; border: none; } body{ background-color: Purple; padding: 20px; font-family: "微软雅黑", "宋体"; } /*按钮自身的容器*/ .Container{ height: 32px; width: 200px; position: relative; } /*按钮左中右容器基本样式设定*/ .Left, .Center, .Right{ background-image: url('btn_bg_noShadow.png'); } .Left{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px 0px; } .Center{ width: 188px; height: 100%; background-repeat: repeat-x; color: White; text-align: Center; font-size: 14px; line-height: 32px; background-position: 0px -35px; } .Right{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px -70px; } </style> </head> <body> <div id="floatContainer" class="Container"> <div class="Left" style="float: left;"></div> <div class="Center" style="float: left;">Float方式模拟的按钮</div> <div class="Right" style="float: right;"></div> </div> <br /> <div id="absoluteContainer" class="Container"> <div class="Left" style="position:absolute;left: 0px;"></div> <div class="Right" style="position:absolute;left: 194px;"></div> <div class="Center" style="position:absolute;left: 3px; width: 194px;">Absolute方式模拟的按钮</div> </div> </body> </html>
下面是测试效果图,这里只选取一些有代表性的截图了。
IE7 |
跟前面未加偏移的版本没有任何区别!故而免图!
|
IE8 |
|
IE9 |
参见上面IE8的截图,IE9的改善甚至更明显!
|
Firefox |
|
Opera |
|
Chrome |
|
Safari |
|
iPhone Safari Mobile |
|
Android 自带浏览器 |
本来就很完美,免图!
|
Android Firefox |
|
Android Opera Mobile |
|
到现在为止,我们几乎可以说,通过偏移尝试消除按钮裂缝和视觉偏移的实验成功了!
7、有没有遗留问题?
答案是确定的,有!什么问题?
前面的例子背景图片使用了边角透明的png图片,所以渲染出来的结果可以成功的透出背景,视觉效果非常好,那么如果更进一步,给背景图片边缘加上半透明的投影效果,那又会如何呢?我们继续测试!
首先是修改添加了投影效果之后的背景图(左右各让出1个像素给投影,下面2个像素的投影)
对应的CSS代码和html代码也略作修改(Left和Right的真实边缘部分都变成了4像素,所以对应的偏移和覆盖也修正为2像素,按钮高度变成了35像素,然后删掉那个用不着的Float定位按钮)
代码如下:
<!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> <title>Browser Tester</title> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style type="text/css"> *{ margin: 0px; padding: 0px; border: none; } body{ background-color: Purple; padding: 20px; font-family: "微软雅黑", "宋体"; } /*按钮自身的容器*/ .Container{ height: 35px; width: 200px; position: relative; } /*按钮左中右容器基本样式设定*/ .Left, .Center, .Right{ background-image: url('btn_bg_shadow.png'); } .Left{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px 0px; } .Center{ width: 188px; height: 100%; background-repeat: repeat-x; color: White; text-align: Center; font-size: 14px; line-height: 32px; background-position: 0px -35px; } .Right{ width: 6px; height: 100%; background-repeat: no-repeat; background-position: 0px -70px; } </style> </head> <body> <br /> <div id="absoluteContainer" class="Container"> <div class="Left" style="position:absolute;left: 0px;"></div> <div class="Right" style="position:absolute;left: 194px;"></div> <div class="Center" style="position:absolute;left: 4px; width: 192px;">Absolute方式模拟的按钮</div> </div> </body> </html>
效果图我们在这里只找一个浏览器作为代表,就选Opera吧,大家知道前面Opera还有个渲染超界的问题呢:
上面是不带阴影的按钮效果,下面是带了阴影的效果,对比一下,果然是带阴影的效果更自然,跟背景融合更好,可是等一下……怎么感觉好像哪里有点不对?我们放大来看一下:
囧了!放大后发现三个问题:
A 、两侧Left和Right分别与Center重叠的部分阴影叠加造成比其他地方更重的颜色,活像闹钟的两个支撑腿
B 、右侧的渲染超界依然存在
C 、底下也出现了渲染超界(把按钮高度改为34像素后消失)
问题A很容易理解,我们用叠加的方式来避免按钮裂缝,那么半透明的阴影叠加在一起当然会显出双重的效果。问题B也不意外,因为本来就有,问题C就有些郁闷了。
解决方法尝试结果:
尝试结果1:
经过多次试验,把按钮高度改为34像素,Opera底下的渲染超界消失(这就是我为什么明明按钮加阴影高度是34像素,我却要把背景图做成35像素的原因了),但是右侧的超界却无法用同样的方法解决!请看效果图:
尝试结果2:
对于问题A我唯一能想到的方案是一个笨办法,把背景图中Left和Right下部投影中可能会与Center投影重合的部分切掉(本文例子当中是各2个像素),变成全透明,这样可以避免所有浏览器下的“闹钟腿”问题了,当然也会带来一点负面的影响,就是在Chrome或者Safari中某些时候有可能会出现阴影部分1个像素的缺失,但是这个缺失相比重叠来讲,几乎从视觉上无法感知到。
先看裁切掉部分阴影后的背景图:
再看最终的效果图:
考虑到渲染超界的问题仅仅在 Opera 超高放大倍数时才会出现,因此我们可以说,到目前为止,所有的遗留问题也基本有了解决方法,虽然可能还不很完美,但是没关系,出现这些问题的原因本身不就是因为浏览器们自己不完美么?而且我们之前想出的种种解决方案也正是利用浏览器的不完美去弥补浏览器的不完美!就好像CSS Hack一样!所以无需再对自己继续苛求了!
五、总结和建议
这注定是一篇不会怎么惹人关注的文章,着眼点既不是技术前沿,也不是创新概念,从头至尾都在跟几个浏览器上的1个像素2个像素死较劲,很多人肯定觉得我故意在跟各大浏览器顶牛,有时候我也怀疑自己是不是真的闲的蛋疼:)
但其实我知道,之所以去钻这个牛角尖,恰恰是因为我自己真正把用户体验放在了第一位!做一个真正的产品,没有好的用户体验,哪怕你再好的创意,最终也会一事无成!什么是用户体验?消灭掉这1个像素的偏差当然不能等于好的用户体验,可是我却知道可能就是那1像素的偏差会让用户体验变得很糟糕!
如果您是单纯编写代码的程序员,可能不明白我说的是什么,但如果您做过产品经理或者UED相关的工作,您会理解我的苦心。
呵呵,一不小心又开始吐槽了,书归正传,总结一下这篇长文所获得的启示吧:
1、现阶段做互联网产品,已经不能仅仅考虑电脑平台(Windows/Linux/Mac)上的浏览器兼容性了,智能手机和类平板电脑的产品同样需要考虑;
2、小屏幕(7寸以下)便携终端浏览器通常都会有缩放功能,而且默认状况下网页都会被放大浏览,因此Web页面效果不仅要看100%状态,还要放大看,本来很棒的视觉效果,没准儿一放大就走样的很离谱;
3、建议尽量对大众保有量较高且又与众不同的设备和浏览器(比如iPhone和Android手机)开发专用的适配版本网页;
4、浏览器也会犯错误,如果你的Web产品看起来在兼容性上有问题,其实不能排除是某个浏览器自身的问题,有时候你不得不去为他们的Bug背书;
5、不同浏览器在对页面进行缩放操作的时候渲染会出问题,本文就有一个很突出的例子,很多浏览器对CSS中Float和Absolute定位的解析和渲染并不十分精准,因此可能会造成页面元素走形,而这其中Float又比Absolute更容易出问题;
6、同样在缩放操作下,大多数浏览器对位图的渲染差异就更大,这会带来小屏幕设备上浏览时的视觉偏差,降低用户体验;
7、针对“由数个宽度不固定的连续元素组合而成的视觉效果”这类的处理需要(比如模拟按钮、模拟导航栏、模拟窗体边框、大图片切割展示等),为了避免出现5和6所描述的问题,可以采用结合部2像素重叠的方法来避免割裂。
8、网页中的半透明过渡图片效果会非常的棒,不过在有可能拼接和重叠的地方使用起来要慎重,如果可以的话,尽量采用半透明层的方式来实现。
追求浏览器兼容性的本质其实就是用它的一个缺憾去掩盖另一个缺憾!
这篇折磨了我整个周末的文章终于到了收尾的阶段,说实话很少这么费心费力的写一篇技术文章,所以到了最后反而有些不舍得搁笔,本人技术有限,水平不高,文中难免出现偏颇乃至谬误,望大家多多指正,不管怎样,希望这篇文章所做的努力能够对大家多少有些启发乃至帮助,我就很欣慰了。
最后把本文用到的测试页面代码和图片放在这里,有兴趣的可以自己测试,点击这里下载