上文:IE7與web標准設計(2)
IE歷來被web標准的擁護者所诟病,而當FireFox橫空出世以後,更多的網頁制作者開始關注web標准設計。看著FireFox的市場占有率不停的上升,微軟終於推出了IE7。但IE7是否真的能夠力挽狂瀾,是否真的能夠得到用戶的信任,是否真的能夠得到網頁設計者的認可呢?
且看《IE7的web標准之道》系列文章,和你一起見證IE7的改變!
前言
現在,最令網頁設計者頭痛的問題就是網頁在各個浏覽器中的兼容性。而兼容性差最長見的,也是最令人恐懼的便是“頁面布局混亂”。常常一個頁面在IE6下顯示的非常完美,而到了IE7(或者FireFox)中,則慘的“不堪入目”。到底是什麼讓這些頁面那麼的“水土不服”呢?
其實,這些都是IE6釀下的惡果,IE6對web標准的支持過於不足,甚至理解的有偏差,才導致了這些頁面的“脆弱”。而IE7則修正了很多的那種“IE6對css解釋和渲染”的bug。這種bug有很多。今天,這裡只講其中一個,但是確是最重要的一個,很多的“十分”混亂的頁面都是它造成的。可以不客氣地說,它簡直就像“頁面布局混亂黑幫”的幕後黑手,是引起頁面布局混亂的禍首之一,而且是最大的一個。 它就是潛伏在網頁背後的“‘overflow:visible’IE6渲染bug”。
“不堪入目”的網頁截圖
如果只是簡單的說“‘overflow:visible’IE6渲染bug”,你可能完全沒有印象。但是看看下面的這些“不堪入目”的網頁截圖,便能引起你心中那無限的傷感……
圖:這是在IE6中顯示的效果截圖,“十分完美”
這是在IE7中顯示的“不堪入目”的效果截圖
上面的兩張截圖,是我2007年在高達軟件公司的真實項目截圖。可以看出,在IE7下的顯示已經嚴重變形,雖然不影響軟件的功能使用,但是已經嚴重的影響了用戶的使用體驗(沒有人喜歡拖動橫向滾動條)。
再看看下面的這個網頁截圖,它是我們今天將要使用的例子(源代碼在下方有提供),是一個標准的“上左右下”帶側邊欄的虛擬網頁。
運行代碼框
[Ctrl+A 全部選擇 提示:你可先修改部分代碼,再按運行]
圖:這是在IE6中顯示的效果截圖,還算“整齊”
而當你展開下面這個折疊區域,去看這個頁面在IE7下顯示的效果圖的時候,可能便會大吃一驚了。
圖:這是在IE7中顯示的效果截圖,已經“不堪入目”了
我們驚訝的看到,網頁“頭部”變“矮”了,最後兩句重要的句子“消失”了;側邊欄變“窄”了,那個重要的網址的後半部消失了(其實是被右面綠色的區域遮蓋住了);而最令人沮喪的是,右面“缺了個大口子”。原本整齊的布局,已經完全消失,出現的是一個“一塌糊塗”的頁面。
到底是什麼,將一個原本好好的頁面“糟蹋”成這樣?且看下面的詳細講解……
圖:這是在FireFox中顯示的效果截圖,已經亂的“令人抓狂”了
為什麼在FireFox又有這麼令人抓狂的顯示呢?原來,這便是IE7的web標准之道的精髓了。隨著web標准的推廣和認可度的提高,IE7必須向web標准靠攏,但是有必須兼顧到,那些現在在IE6中還顯示正常的億萬個已經存在的頁面。這樣矛盾就產生了——遵循標准就意味著頁面會顯示的亂七八糟,甚至無法浏覽;但是如果太過於兼容IE6的那些爛攤子網頁,又必然會離web標准越來越遠。於是IE7走出了自己的web標准之道——絕對重視web標准,又稍微兼顧IE6的爛攤子。於是,IE7顯示的那個頁面雖然已經亂了,但是還不像在FireFox中顯示的那樣令人抓狂。
附:測試頁面在Opera(版本9.25)中的顯示效果截圖(寫文章的時候Opera正好有了新的升級版本)
圖:這是在Opera中顯示的效果截圖,“亂的程度”和FireFox是一樣的
“非也,非也”
“千萬別用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/" />
<title>YES!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/" 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條:
有些朋友可能會問,你怎麼知道任意有寬度和高度概念的“可見元素”,它們在默認狀態下的“overflow”樣式的值都是“Visible”的呢?
其實方法很簡單,利用IE Developer Toolbar這個工具就可以知道了。下面的文章和截圖,可能會對你有幫助:
文章: 《介紹兩個,b/s開發中我常用到的小工具》
截圖:
圖:利用“IE Developer Toolbar”得到元素樣式的默認值
如何修復bug
其實這個bug,我們還是有辦法修復的,但都不是很完美的解決方案,想要取得較好的效果,還需要一些技巧。下面便是我工作中總結的一套解決方案。小弟才疏,眾多不對之處,還請各位高手指教。
修正這個bug首先要洗腦一下,因為錯誤的認識將不利於你對解決方法的理解。
如何解決“橫向撐開”問題
用“word-wrap: break-word”解決:
導致布局混亂的主要原因,是IE6對overflow的visible的錯誤解釋,才導致寬度被“撐開”才造成的。所以,我們必須采取措施,讓IE6中容器不能那麼“放縱孩子”才可以。方法就是使用“word-wrap: break-word”樣式(IE特有,FireFox不起任何作用),強制要求容器內的內容不允許“撐開”父容器。下面的示例可能有助於理解。
利用“word-wrap: break-word”可以讓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/" />
<title>YES!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中,容器也不再被“撐開”
用“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/" />
<title>YES!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中終於顯示一致了
一個大問題與殘缺的美麗
從截圖看,網頁在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/" />
<title>YES!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.length>intLen){
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容器裡面的標簽和樣式也將失去,只留下文本……
另一個“焦油坑”——“縱向撐開”
上面解決方法,只是“橫向”的、寬度的問題,其實“‘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/" />
<title>YES!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”,上面從多個方向和角度進行了講解。雖然有些方面還不能有完美的解決方案,但是在更理性的解決方案出現之前,暫時也是沒有辦法的事情,只能留個遺憾在那裡,因為我們還要繼續前進……