Web前端瀏覽器兼容初探,小生淺文拋磚引玉,期待高手攻破難關!


前言

瀏覽器兼容是前端開發人員必須掌握的一個技能,但是初入前端的同學或者其他后台web開發同學往往容易選擇忽略,而形成兩個極端:

1 我最開始都是使用IE6,IE6上沒問題,其它瀏覽器坑爹(多出現與前端后端一起搞的同學,小生2年前就這種狀態,鼓勵人家用ie6.。。。)

2 我要遵循標准,我只要ff就好,IE就是坑爹的玩意,我不必去理他(小生一年前的心態。。。)

現在看來,之前的想法都是不對的,我們誠然應該追求最新的瀏覽器使用最新的技術,但是漸進增強,向后兼容的思想一定要有,

因為就現在IE6在中國的份額也是不容小視的。

拋開之前的大道理,我們說點實際的問題,哪次前端面試不問兼容性問題?哪次我們又能回答的很好?反正我就沒一次說好的,知不足然后能改,

我前端時間便經過整理形成這篇文章,文章有很多不足,希望各位指正、補充,后面若是能形成一篇較全面的前端兼容文章就善莫大焉了!

為什么會有兼容問題?

由於市場上瀏覽器種類眾多,而不同瀏覽器其內核亦不盡相同,所以各個瀏覽器對網頁的解析就有一定出入,這也是導致瀏覽器兼容問題出現的主要原因,我們的網頁需要在主流瀏覽器上正常運行,就需要做好瀏覽器兼容。

使用Trident內核的瀏覽器:IE、Maxthon、TT;

使用Gecko內核的瀏覽器:Netcape6及以上版本、FireFox;

使用Presto內核的瀏覽器:Opera7及以上版本;

使用Webkit內核的瀏覽器:Safari、Chrome。

而我現在所說的兼容性問題,主要是說IE與幾個主流瀏覽器如firefox,google等。

而對IE瀏覽器來說,IE7又是個跨度,因為之前的版本更新甚慢,bug甚多。從IE8開始,IE瀏覽器漸漸遵循標准,到IE9后由於大家都一致認為標准很重要,可以說在兼容性上比較好了,但是在中國來說,由於xp的占有率問題,使用IE7以下的用戶仍然很多,所以我們不得不考慮低版本瀏覽器的兼容。

對瀏覽器兼容問題,我一般是這樣分類的,HTML,Javascript兼容,CSS兼容。 其中html相關問題比較容易處理,無非是高版本瀏覽器用了低版本瀏覽器無法識別的元素,導致其不能解析,所以平時注意一點就是。特別是HTML5增加了許多新標簽,低版本瀏覽器有點影響時代進步啊;

javascript兼容性問題

在javascript中,各個瀏覽器基本語法差距不大,其兼容問題主要出現在各個瀏覽器的實現上,尤其對事件的支持有很大問題,在此我就說說我知道的幾個問題。

① 在標准的事件綁定中綁定事件的方法函數為 addEventListener,而IE使用的是attachEvent

② 標准瀏覽器采用事件捕獲的方式對應IE的事件冒泡機制(即標准由最外元素至最內元素或者IE由最內元素到最外元素)最后標准方亦覺得IE這方面的比較合理,所以便將事件冒泡納入了標准,這也是addEventListener第三個參數的由來,而且事件冒泡作為了默認值。

③ 事件處理中非常有用的event屬性獲得亦不相同,標准瀏覽器是作為參數帶人,而ie是window.event方式獲得,獲得目標元素ie為e.srcElement 標准瀏覽器為e.target

④ 然后在ie中是不能操作tr的innerHtml的

⑤ 然后ie日期函數處理與其它瀏覽器不大一致,比如: var year= new Date().getYear(); 在IE中會獲得當前年,但是在firefox中則會獲得當前年與1900的差值。

⑥  獲得DOM節點的方法有所差異,其獲得子節點方法不一致。

IE:parentElement parentElement.children Firefox:parentNode parentNode.childNodes childNodes的下標的含義在IE和Firefox中不同,Firefox使用DOM規范,childNodes中會插入空白文本節點。一般可以通過node.getElementsByTagName()來回避這個問題。

當html中節點缺失時,IE和Firefox對parentNode的解釋不同。例如:

<form>  <table>   <input/>  </table> </form> IE:input.parentNode的值為空節點 Firefox:input.parentNode的值為form 解決方法:Firefox中節點沒有removeNode方法,必須使用如下方法 node.parentNode.removeChild(node)

⑦ 關於AJAX的實現上亦有所不同;

就javascript來說,各大瀏覽器之間的差異還是不少的,但是具體我變得這里都不大關注了,因為我們開發過程中一般都會使用類庫,若是不使用,都會自己積累形成一個類庫,所以就js而言,兼容性問題基本解決了。

讓人頭疼的CSS兼容

因為之前對css的理解不夠深入,也沒有經過系統的學習,所以一度認為css是前端最難的東西,但真的學習后,才發現css真的很難。。。有很多東西啊!!!

我覺得最讓人頭疼的問題還是CSS問題,因為一點點布局上的bug,可能導致整個頁面的錯位,在用戶看來這是極不專業的。

現在我就簡要說說我對CSS兼容問題的認識: 先說點Hack的知識(真正的高手是不用Hack的,但要成為高手必須通過Hack這一關

/* CSS屬性級Hack */ 

color:red; /* 所有瀏覽器可識別*/ 

_color:red; /* 僅IE6 識別 */ 

*color:red; /* IE6、IE7 識別 */ 

+color:red; /* IE6、IE7 識別 */ 

*+color:red; /* IE6、IE7 識別 */ 

[color:red; /* IE6、IE7 識別 */ 

color:red\9; /* IE6、IE7、IE8、IE9 識別 */ 

color:red\0; /* IE8、IE9 識別*/ 

color:red\9\0; /* 僅IE9識別 */ 

color:red \0; /* 僅IE9識別 */ 

color:red!important; /* IE6 不識別!important 有危險*/

/* CSS選擇符級Hack */ 

*html #demo { color:red;} /* 僅IE6 識別 */ 

*+html #demo { color:red;} /* 僅IE7 識別 */ 

body:nth-of-type(1) #demo { color:red;} /* IE9+、FF3.5+、Chrome、Safari、Opera 可以識別 */ 

head:first-child+body #demo { color:red; } /* IE7+、FF、Chrome、Safari、Opera 可以識別 */ 

:root #demo { color:red\9; } : /* 僅IE9識別 */

/* IE條件注釋Hack */ 

<!--[if IE 6]>此處內容只有IE6.0可見<![endif]--> 

<!--[if IE 7]>此處內容只有IE7.0可見<![endif]-->

接下來說說一些我知道的BUG:

① css盒模型在IE6下解析有問題,我們知道就width來說,一個塊級元素的magin、padding、boder,width7個屬性的寬度之和,應該等於其父級元素的內容區域(width),
而我們一般設置寬度若是未達到其長度,瀏覽器就會重置margin-right的值,將之它們的和等於其值,當然若是我們為margin設置負值,那么元素的width可能超出其父元素。
在標准下,width為padding所占區域,但是再ie6中設置width后,其真實width為所設width-其padding與border*2,我一般采用CSShack技術處理
② IE6的雙倍邊距BUG,在塊級元素浮動后本來外邊距10px,但IE解釋為20px,解決辦法是加上display: inline ,

1、問題:在IE6下如果某個標簽使用了float屬性,同時設置了其外補丁“margin:10px 0 0 10px”可以看出,上邊距和左邊距同樣為10px,但第一個對象距左邊有20px。

2、解決辦法:當將其display屬性設置為inline時問題就都解決了。

3、說明:這是因為塊級對象默認的display屬性值是block,當設置了浮動的同時,還設置了它的外邊距 就會出現這種情況。
也許你會問:“為什么第二個對象和第一個對象之間就不存在雙倍邊距的BUG”?
因為浮動都有其相對應的對象,只有相對於其父對象的浮動 對象才會出現這樣的問題。
第一個對象是相對父對象的,而第二個對象是相對第一個對象的,所以第二個對象在設置后不會出現問題。
另外在一些特殊布局中,可能需要組合使用display:block;和display:inline;才能達到預期效果。
當然最壞的情況下,我們就可以使用"margin:10px 0 0 10px;*margin:10px 0 0 10px;_margin:10px 0 0 5px"
這種“標准屬性;*IE7識別屬性;_IE6識別屬性”HACK方式解決 4、總結:這個現象僅當塊級對象設置了浮動屬性后才會出現,內聯對象(行級對象)不會出現此問題。並且只有設置左邊距和右邊距的值才會出問題,上下邊距不會出現問題。 <div style="width:200px;height:50px;background:#ccc;"> <div style="width:100px; height:50px;float:left;margin-left:10px; background:#eee;"> </div> </div> margin雙布局可以說是IE6下經典的bug之一。產生的條件是:block元素+浮動+margin。 還記得我自認為會css的那個階段,這個問題我經常碰到,會很熟練的用hack解決這個問題,當時還自以為是,洋洋得意。現在看來,當時的自己嫩的就像個 豆芽菜。
真正css厲害的人基本上是不會碰到這個bug的,如果您時不時遇到這個bug,說明您的css還有好一段路要走。 我的體會是越少的浮動,就會越少的代碼,會有更靈活的頁面,會有擴展性更強的頁面。這不多說,歸結為到一定水平了,浮動會用的較少。
另外,您也會避免使用浮動
+margin的用法。所以,越后來越不易遇到這種bug。 這里提一下解決方法,使用hack我是不推薦的,使用hack屬於比初學者稍高一點的層次水平。一個頁面,沒有一個hack,但是各個瀏覽器下表現一致,這才是水平。
使用display:inline;可以解決這個問題。 而為什么display:inline可以解決這個雙邊距bug,首先是inline元素或inline
-block元素是不存在雙邊距問題的。
然后,float:left等浮動屬性可以讓inline元素haslayout,會讓inline元素表現得跟inline-block元素的特性一樣, 支持高寬,垂直margin和padding等,
所以div class的所有樣式可以用在這個display inline的元素上。
③ IE6下圖片下方有空隙產生;解決這個BUG的方法也有很多,可以是改變html的排版,或者設置img 為display:block,
或者設置vertical-align 屬性為vertical-align:top bottom middle text-bottom都可以解決.(但是最近我發現這個問題在其它瀏覽器中也有所體現)
④ IE6 3px bug 兩個浮動層中間有間隙,這個IE的3PX BUG也是經常出現的,
解決的辦法是給右邊元素也同樣浮動 float:left 或者相對IE6定義.left margin-right:-3px; 
經典兩列布局,float: left;width:200px; 第二個,margin-left,200px; 他們之間會產生3px的間距。
⑤ 在IE6中沒有min-width的概念,其默認width就是min-width,所以有時字體過多它會選擇撐開容器。
⑥ IE6無法定義1px左右高度的容器,是因為默認的行高造成的,解決的方法也有很多,
例如: overflow:hidden zoom:0.08 line-height:1px ⑦ 使用margin : 0 auto;方法使容器居中依然在IE6中行不通,我們要對其父容器使用text-align:center;
⑧ 被點擊訪問過的超鏈接樣式不在具有hover和active了,很多人應該都遇到過這個問題,
解決方法是改變CSS屬性的排列順序: L-V-H-A <style type="text/css">   a:link {}  a:visited {}  a:hover {}  a:active {} /style>
⑨ 在使用絕對定位/相對定位時,設置z-index在ie中可能會失效,是因為其元素依賴於其父元素的z-index,而父元素默認為0 ?
所以子元素z-index高,而父元素底,依然不會改變其顯示順序;
10、外邊距疊加問題:

#box{ margin:10px; background-color:Red; }

#box p { margin:20px; background:gray; }

<div id="box"><p>dd</p></div>

該代碼會導致外邊距疊加,並且外邊距跑到div包裹外去,bug是由於塊級子元素高度計算方式造成的。 
若是元素沒有垂直邊框或者padding,那么它的高度就是包含的子元素的頂部和底部邊框的的距離。

以上便是我所記得的一些bug,在這里我再順帶提一下haslayout(IE8廢棄該屬性)。

在IE低版本瀏覽器時基本是表格布局的時代,幾乎是所有的元素(除內聯元素)都是一個盒子,內容不會超過表格的單元格,表格的單元格也不會超出表格。

在IE6推出后,CSS改變這一假設——因為CSS允許內容超出元素。 因此haslayout這個屬性就誕生了。

在IE6,IE7中,每個元素都有haslayout這個屬性,可以設置為 true 或者 false。
如果設置為true,元素就必須去自我布局和渲染,因此元素會擴展去包含它溢出的內容,例如浮動或沒截斷的單詞。
如果haslayout 沒有被設置成true,那么元素需依靠某個祖先元素來渲染它。這就是很多的ie bugs誕生的地方。IE瀏覽器下的很多bug都是haslayout = false 引起的,
layout元素有以下特點:  

1、擁有布局(haslayout=true)元素不會收縮,所以可能會發生文字截斷、消失的現象;

2、布局元素對浮動自動清理;

3、相對定位的元素沒有布局,這可能導致絕對元素定位偏差;

4、擁有布局的元素外邊距不疊加;

5、滾動時,頁面會有所跳動;

6、邊框消失

7、像素偏差

haslayout不是一個CSS屬性,所以我們不能這樣的來設置它 haslayout:true;

一個元素被設置成haslayout:true將被渲染成一個 having haslayout,

反之同理。 一些元素本身該屬性為true,若是需要觸發,最好的方法是設置其zoom屬性; 哪些元素本身就 haslayout:true

<html>, <body><table>, <tr>, <th>, <td><iframe>, <embed> (non-standard element),

<object>, <applet> <img><hr><input>, <button>, <select>, <textarea>, <fieldset>, <legend>

 zoom:1,被認為是最好的觸發Layout的方法,因為它對當前元素沒有影響。 觸發haslayout,相對來說比haslayout=false要簡單。

以下屬性和值將給定一個元素進行布局

position: absolute float:    left or right display:    inline-block;width:   any value other than auto;

height:    any value other than auto;zoom:   any value other than normal (*);writing-mode:  tb-rl

最后,因為各個瀏覽器對一些元素的默認值設置不一致也會導致表現差異,比如瀏覽器默認字體,默認行高,默認間距等。所以我們一般會為幾個主要元素設置默認值。

結語

以上便是我對瀏覽器兼容的簡單認識,但是還是有很多不足的地方,由於技術所限,這里提出來和各位高手交流,希望在交流學習中和以后工作中積累相關經驗,做出滿足主流瀏覽器的網頁;

 如果你覺得這篇文章還不錯,請幫忙點擊一下推薦,謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM