序章
- 談?wù)劇盀g覽器兼容性”的問題?
- 很多前端的面試或筆試中,都有比較籠統(tǒng)的“說說你所知道的各瀏覽器存在的兼容問題”,個人感覺這個問題問的太“大”了些,從樣式到腳本,都會有很多不一樣的地方(特別是IE8-對比主流瀏覽器)。實際回答的時候就會暈乎乎的不清楚如何抓住重點地來闡述。到底怎樣回答這個問題,才能較為全面又不失重點,并讓面試官感到滿意呢?
- 首先明確一個概念,“談?wù)劄g覽器兼容性”的問題和“說說你所知道的各瀏覽器存在的兼容問題”是兩個完全不同的問題。
- 前者,鬼知道他想要問什么,得追問。
比如得問“您說的是哪個瀏覽器的哪類問題?還是常用瀏覽的(前端)API差異?渲 染差異?等等。還是要談?wù)劄g覽器為什么存在兼容問題?兼容存在的歷史原因?歷史必然性等等”。
后者,基本上是個有著較明確邊界范圍的開放問題。
基本上可以知道,他是想了解你常用的常見到的常解決到的,或者近期剛剛解決過的一些瀏覽器兼容問題。從而判斷你這部分知識面、解決問題的思路等等方面內(nèi)容,而且不像前者一樣慢無邊界的。
起碼,這么問的是不太閑,不想陪你嘮嗑的。 - 如果面試官糾結(jié)于你沒回答出某個兼容性問題,即使要了你也不要去。 特別是那種還在炫耀IE6+ 1px技能的老先生。 現(xiàn)在還談IE6+兼容性的面試官,真的挺掉公司的價的。
- 下面我們由淺到深,由簡到易的回答這個籠統(tǒng)的“瀏覽器兼容性”問題!
CSS篇
1. 一些常見問題匯總
-
瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J的外補丁和內(nèi)補丁不同
問題癥狀:隨便寫幾個標(biāo)簽,不加樣式控制的情況下,各自的margin 和padding差異較大。
碰到頻率:100%
解決方案:CSS里 *{margin:0;padding:0;}
備注:這個是最常見的也是最易解決的一個瀏覽器兼容性問題,幾乎所有的CSS文件開頭都會用通配符*來設(shè)置各個標(biāo)簽的內(nèi)外補丁是0。 -
瀏覽器兼容問題二:塊屬性標(biāo)簽float后,又有橫行的margin情況下,在IE6顯示 margin比設(shè)置的大
問題癥狀:常見癥狀是IE6中后面的一塊被頂?shù)较乱恍?br> 碰到頻率:90%(稍微復(fù)雜點的頁面都會碰到,float布局最常見的瀏覽器兼容問題)
解決方案:在float的標(biāo)簽樣式控制中加入 display:inline;將其轉(zhuǎn)化為行內(nèi)屬性
備注:我們最常用的就是div+CSS布局了,而div就是一個典型的塊屬性標(biāo)簽,橫向布局的時候我們通常都是用div float實現(xiàn)的,橫向的間距設(shè)置如果用margin實現(xiàn),這就是一個必然會碰到的兼容性問題。 -
瀏覽器兼容問題三:設(shè)置較小高度標(biāo)簽(一般小于10px),在IE6,IE7,遨游中高度超出自己設(shè)置高度
問題癥狀:IE6、7和遨游里這個標(biāo)簽的高度不受控制,超出自己設(shè)置的高度
碰到頻率:60%
解決方案:給超出高度的標(biāo)簽設(shè)置overflow:hidden;或者設(shè)置行高line-height 小于你設(shè)置的高度。
備注:這種情況一般出現(xiàn)在我們設(shè)置小圓角背景的標(biāo)簽里。出現(xiàn)這個問題的原因是IE8之前的瀏覽器都會給標(biāo)簽一個最小默認的行高的高度。即使你的標(biāo)簽是空的,這個標(biāo)簽的高度還是會達到默認的行高。 -
瀏覽器兼容問題四:行內(nèi)屬性標(biāo)簽,設(shè)置display:block后采用float布局,又有橫行的margin的情況,IE6間距bug
問題癥狀:IE6里的間距比超過設(shè)置的間距
碰到幾率:20%
解決方案:在display:block;后面加入display:inline;display:table;
備注:行內(nèi)屬性標(biāo)簽,為了設(shè)置寬高,我們需要設(shè)置display:block;(除了input標(biāo)簽比較特殊)。在用float布局并有橫向的margin后,在IE6下,他就具有了塊屬性float后的橫向margin的bug。不過因為它本身就是行內(nèi)屬性標(biāo)簽,所以我們再加上display:inline的話,它的高寬就不可設(shè)了。這時候我們還需要在display:inline后面加入display:talbe。 -
瀏覽器兼容問題五:圖片默認有間距
問題癥狀:幾個img標(biāo)簽放在一起的時候,有些瀏覽器會有默認的間距,加了問題一中提到的通配符也不起作用。
碰到幾率:20%
解決方案:使用float屬性為img布局
備注:因為img標(biāo)簽是行內(nèi)屬性標(biāo)簽,所以只要不超出容器寬度,img標(biāo)簽都會排在一行里,但是部分瀏覽器的img標(biāo)簽之間會有個間距。去掉這個間距使用float是正道。(我的一個學(xué)生使用負margin,雖然能解決,但負margin本身就是容易引起瀏覽器兼容問題的用法,所以我禁止他們使用) -
瀏覽器兼容問題六:標(biāo)簽最低高度設(shè)置min-height不兼容
問題癥狀:因為min-height本身就是一個不兼容的CSS屬性,所以設(shè)置min-height時不能很好的被各個瀏覽器兼容
碰到幾率:5%
解決方案:如果我們要設(shè)置一個標(biāo)簽的最小高度200px,需要進行的設(shè)置為:{min-height:200px; height:auto !important; height:200px; overflow:visible;}
備注:在B/S系統(tǒng)前端開時,有很多情況下我們又這種需求。當(dāng)內(nèi)容小于一個值(如300px)時。容器的高度為300px;當(dāng)內(nèi)容高度大于這個值時,容器高度被撐高,而不是出現(xiàn)滾動條。這時候我們就會面臨這個兼容性問題。
2. CSS hack
請謹(jǐn)慎使用 css hack
In modern computing terminology, a kludge (or often a "hack") is a solution to a problem, doing a task, or fixing a system that is inefficient, inelegant, or even unfathomable, but which nevertheless (more or less) works.
(from wiki: Kludge)
也就是說,hack 是不優(yōu)雅的、不是最有效的,甚至是不能理解的,但是能搞定問題的解決辦法。
那么 CSS hack 呢?CSS hack 就是利用瀏覽器一些不標(biāo)準(zhǔn)的,或者可以稱之為 bug 的特性,達到特定的目的。最常見的各種 hack 是關(guān)于 ie 的,尤其是舊版本 ie。這種 hack 比較無奈,但是相對安全,因為舊版本 ie 不再更新了,不會發(fā)生變化了。
但是,如果用一些當(dāng)前瀏覽器的 bug 來 hack,就是有危險的了。這種 hack 建立在不穩(wěn)定的瀏覽器特性上,沒有標(biāo)準(zhǔn)可依。當(dāng)瀏覽器廠商修復(fù)/標(biāo)準(zhǔn)化了這個特性的時候,hack 就可能失效。這樣就解釋了問題的這句話。說實話,筆者到現(xiàn)在為止還沒有用到過CSS hack。個人認為原因有三:1. 筆者太菜,遇到的場景不夠豐富,運氣好沒有踩到過坑;2.一些瀏覽器bug已經(jīng)隨著瀏覽器的版本更新被修復(fù)掉;3.遇到要使用CSS hack的情況了卻沒有意識到,換了種方式去實現(xiàn)了。最最最最究極原因,筆者所在的公司不需要支持 IE9 一下的老古董,甚至在某些項目里可以直接舍棄掉IE,是不是很羨慕?
JS篇
1. 集合類對象的()與[]的問題
IE下,可以使用()或[]獲取集合類對象;Firefox下,只能使用[]獲取集合類對象。
Js代碼 :
document.write(document.forms("formName").src);
//該寫法在IE下能訪問到Form對象的src屬性
解決辦法:將document.forms("formName")改為 document.forms["formName"]。統(tǒng)一使用[]獲取集合類對象。
2. 對瀏覽器Native組件調(diào)用屬性、方法大小寫問題
IE:不區(qū)分大小寫
FF、Chrome:區(qū)分大小寫
如:Ajax返回的response對象,IE支持response.responseXml和responseXML;FF等瀏覽器支持response.responseXML,解決辦法只有在編寫程序時盡量避免不兼容的寫法
3. new Date().getYear()
分析原因:在IE中得到的日期是2011,在FF和Safari中看到的日期是111,原因是在FF和safari返回的是當(dāng)前年份-1900的值。
兼容處理:
Js代碼:
//方式一
var year= new Date().getYear();
year = (year<1900?(1900+year):year);
document.write(year);
//方式二
var year = new Date().getFullYear();
document.write(year);
4. innerText的使用
分析原因:FF不支持innerText,它支持textContent來實現(xiàn)innerText,不過textContent沒有像innerText一樣考慮元素的display方式,所以不完全與IE兼容。如果不用textContent,字符串里面不包含HTML代碼也可以用innerHTML代替。
兼容處理
通過判斷不同瀏覽器做不同的處理
Js代碼 javascript
if(document.all){
document.getElementById('element').innerText = "mytext";
} else{
document.getElementById('element').textContent = "mytext";
}
注:Safari和Chrome對innerText和textContent都支持。
5. Frame的引用
【分析原因】
IE可以通過id或者name訪問這個frame對應(yīng)的window對象;而FF只可以通過name來訪問這個frame對應(yīng)的window對象。
【應(yīng)用場景】
在一個頁面嵌套了一個iframe頁面(下面簡稱父頁面和子頁面)。父頁面取子頁面的值。
Js代碼
<iframe id="frame_id" src="frametest.jsp" width="100%" height="100%" title="你好世界">
此時如果父頁面想獲取子頁面例如div中的顯示值,IE下可以這樣寫:
var obj = window.top.frame_id.document.getElementById(div_id);
alert(obj.innerText);
但是在FF中卻無法取子頁面中的值,原因就是FF只支持window.top.frameName來訪問子頁面中的window對象。所以在IE、safari中是支持通過frameName或是frameId來訪問子頁面window對象的。
解決方法:
1、盡量都是用frameName去訪問子頁面window對象。
2、在FF、IE、Safari中都支持window.document.getElementById(frameId)來獲得子頁面window對象。
HTML 篇
- 如有以下這樣一段代碼:
<div id="test">
<p>文字</p>
<p>文字</p>
<p>文字</p>
</div>
單從HTML結(jié)構(gòu)表象來看,ID test 一共有3個P元素子節(jié)點。其實,在IE下,這種表象就是實質(zhì),而在非IE下,表象的外衣將頃刻被撕開。
為了看出這種區(qū)別,我們可以遍歷test的子節(jié)點,并將其節(jié)點個數(shù)及節(jié)點類型都打印出來:
<script type="text/javascript">
var x = document.getElementById("test");
var xc = x.childNodes;
var xcl = xc.length;
for(var i=0;i<xcl;i++){
document.write("nodeName = " + xc[i].nodeName + "; nodeType = " + xc[i].nodeType + "<br />");
</script>
IE的打印結(jié)果為:
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
非IE的打印結(jié)果為:
nodeName = #text; nodeType = 3
nodeName = P; nodeType = 1
nodeName = #text; nodeType = 3
nodeName = P; nodeType = 1
nodeName = #text; nodeType = 3
nodeName = P; nodeType = 1
nodeName = #text; nodeType = 3
顯而易見,IE的打印結(jié)果和我們所說的表象一樣:有3個子節(jié)點,并且都為P元素;而非IE則表現(xiàn)出極大的差異:居然打印出了7個子節(jié)點,當(dāng)然也包括3個P元素子節(jié)點在內(nèi),除此之外還多了4個nodeType=3的子節(jié)點,我們都知道節(jié)點類型為3的節(jié)點屬于文本節(jié)點,但從那段HTML中可以看P與 P之間并無其它的內(nèi)容出現(xiàn),那這4個文本節(jié)點是怎樣憑空出現(xiàn)的呢?
在這種情況下,唯一有可能的原因就是在HTML的書寫上,因為這段HTML并不是連續(xù)的書寫,而是每個節(jié)點間都用回車換行了,并且正好出現(xiàn)了4次換行,也許非IE把換行也當(dāng)成了一個節(jié)點。
為了測試,我們可以將那段HTML改寫為:
<div id="test"><p>文字</p><p>文字</p><p>文字</p></div>
IE的打印結(jié)果為:
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
非IE的打印結(jié)果為:
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
nodeName = P; nodeType = 1
預(yù)想中的情況出現(xiàn)了,這回不論什么瀏覽器打印出來的都只是3個P子節(jié)點。
一些很基礎(chǔ)卻很不起眼的冷知識
- DOCTYPE
1. 作用:聲明文檔的解析類型(document.compatMode),避免瀏覽器的怪異模式。
document.compatMode: BackCompat:怪異模式,瀏覽器使用自己的怪異模式解析渲染頁面。 CSS1Compat:標(biāo)準(zhǔn)模式,瀏覽器使用W3C的標(biāo)準(zhǔn)解析渲染頁面。
這個屬性會被瀏覽器識別并使用,但是如果你的頁面沒有DOCTYPE的聲明,那么compatMode默認就是BackCompat,
這也就是惡魔的開始 -- 瀏覽器按照自己的方式解析渲染頁面,那么,在不同的瀏覽器就會顯示不同的樣式。
如果你的頁面添加了<!DOCTYPE html>那么,那么就等同于開啟了標(biāo)準(zhǔn)模式,那么瀏覽器就得老老實實的按照W3C的標(biāo)準(zhǔn)解析渲染頁面,這樣一來,你的頁面在所有的瀏覽器里顯示的就都是一個樣子了。
這就是<!DOCTYPE html>的作用。
2. 常用的 DOCTYPE 聲明:
HTML 5
<!DOCTYPE html>
HTML 4.01 Strict
該 DTD 包含所有 HTML 元素和屬性,但不包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
HTML 4.01 Transitional
該 DTD 包含所有 HTML 元素和屬性,包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">
HTML 4.01 Frameset
該 DTD 等同于 HTML 4.01 Transitional,但允許框架集內(nèi)容。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
XHTML 1.0 Strict
該 DTD 包含所有 HTML 元素和屬性,但不包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。必須以格式正確的 XML 來編寫標(biāo)記。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
XHTML 1.0 Transitional
該 DTD 包含所有 HTML 元素和屬性,包括展示性的和棄用的元素(比如 font)。不允許框架集(Framesets)。必須以格式正確的 XML 來編寫標(biāo)記。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
XHTML 1.0 Frameset
該 DTD 等同于 XHTML 1.0 Transitional,但允許框架集內(nèi)容。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
XHTML 1.1
該 DTD 等同于 XHTML 1.0 Strict,但允許添加模型(例如提供對東亞語系的 ruby 支持)。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
廢話太多了,你只需要記住每個頁面頭部都寫這么一句話就ok了!
<!DOCTYPE html>
-
瀏覽器渲染原理
Web頁面運行在各種各樣的瀏覽器當(dāng)中,瀏覽器載入、渲染頁面的速度直接影響著用戶體驗簡單地說,頁面渲染就是瀏覽器將html代碼根據(jù)CSS定義的規(guī)則顯示在瀏覽器窗口中的這個過程。先來大致了解一下瀏覽器都是怎么干活的:
1. 用戶輸入網(wǎng)址(假設(shè)是個html頁面,并且是第一次訪問),瀏覽器向服務(wù)器發(fā)出請求,服務(wù)器返回html文件;
2. 瀏覽器開始載入html代碼,發(fā)現(xiàn)<head>標(biāo)簽內(nèi)有一個<link>標(biāo)簽引用外部CSS文件;
3. 瀏覽器又發(fā)出CSS文件的請求,服務(wù)器返回這個CSS文件;
4. 瀏覽器繼續(xù)載入html中<body>部分的代碼,并且CSS文件已經(jīng)拿到手了,可以開始渲染頁面了;
5. 瀏覽器在代碼中發(fā)現(xiàn)一個img標(biāo)簽引用了一張圖片,向服務(wù)器發(fā)出請求。此時瀏覽器不會等到圖片下載完,而是繼續(xù)渲染后面的代碼;
6. 服務(wù)器返回圖片文件,由于圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分代碼;
7. 瀏覽器發(fā)現(xiàn)了一個包含一行Javascript代碼的<script>標(biāo)簽,趕快運行它;
8. Javascript腳本執(zhí)行了這條語句,它命令瀏覽器隱藏掉代碼中的某個
(style.display=”none”)。杯具啊,突然就少了這么一個元素,瀏覽器不得不重新渲染這部分代碼;
9. 終于等到了</html>的到來,瀏覽器淚流滿面……
10. 等等,還沒完,用戶點了一下界面中的“換膚”按鈕,Javascript讓瀏覽器換了一下<link>標(biāo)簽的CSS路徑;
11. 瀏覽器召集了在座的各位span ul li 們,“大伙兒收拾收拾行李,咱得重新來過……”,瀏覽器向服務(wù)器請求了新的CSS文件,重新渲染頁面。
瀏覽器每天就這么來來回回跑著,要知道不同的人寫出來的html和css代碼質(zhì)量參差不齊,說不定哪天跑著跑著就掛掉了。好在這個世界還有這么一群人——頁面重構(gòu)工程師,平時挺不起眼,也就幫視覺設(shè)計師們切切圖啊改改字,其實背地里還是干了不少實事的。
說到頁面為什么會慢?那是因為瀏覽器要花時間、花精力去渲染,尤其是當(dāng)它發(fā)現(xiàn)某個部分發(fā)生了點變化影響了布局,需要倒回去重新渲染,內(nèi)行稱這個回退的過程叫reflow。
reflow幾乎是無法避免的。現(xiàn)在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質(zhì)上是元素的顯示與隱藏)等,都將引起瀏覽器的 reflow。鼠標(biāo)滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內(nèi)部、周圍甚至整個頁面的重新渲染。通常我們都無法預(yù)估瀏覽器到底會reflow哪一部分的代碼,它們都彼此相互影響著。
reflow問題是可以優(yōu)化的,我們可以盡量減少不必要的reflow。比如開頭的例子中的 img 圖片載入問題,這其實就是一個可以避免的reflow——給圖片設(shè)置寬度和高度就可以了。這樣瀏覽器就知道了圖片的占位面積,在載入圖片前就預(yù)留好了位置。
另外,有個和reflow看上去差不多的術(shù)語:repaint,中文叫重繪。 如果只是改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內(nèi)部布局的屬性,將只會引起瀏覽器repaint。repaint的速度明顯快于 reflow(在IE下需要換一下說法,reflow要比repaint 更緩慢)。
- 從瀏覽器的渲染原理講CSS性能
平時我們幾乎每天都在和瀏覽器打交道,寫出來的頁面很有可能在不同的瀏覽器下顯示的不一樣。苦逼的前端攻城師們?yōu)榱思嫒莞鱾€瀏覽器而不斷地去測試和調(diào)試,還在腦子中記下各種遇到的BUG及解決方案,而我們好像并沒有去主動地關(guān)注和了解下瀏覽器的工作原理。如果我們對此做一點了解,我想在項目過程中就可以根據(jù)它有效的避免一些問題以及對頁面性能做出相應(yīng)的改進。今天我們主要根據(jù)瀏覽器的渲染原理對CSS的書寫性能做一點改進,下面讓我們一起來揭開瀏覽器的渲染原理這一神秘的面紗吧:
最終決定瀏覽器表現(xiàn)出來的頁面效果的差異是:渲染引擎 Rendering Engine(也叫做排版引擎),也就是我們通常所說的“瀏覽器內(nèi)核”,負責(zé)解析網(wǎng)頁語法(如HTML、JavaScript)并渲染、展示網(wǎng)頁。相同的代碼在不同的瀏覽器呈現(xiàn)出來的效果不一樣,那么就很有可能是不同的瀏覽器內(nèi)核導(dǎo)致的。
我們來看一下加載頁面時瀏覽器的具體工作流程:
1、解析HTML以重建DOM樹(Parsing HTML to construct the DOM tree ):渲染引擎開始解析HTML文檔,轉(zhuǎn)換樹中的標(biāo)簽到DOM節(jié)點,它被稱為“內(nèi)容樹”。
2、構(gòu)建渲染樹(Render tree construction):解析CSS(包括外部CSS文件和樣式元素),根據(jù)CSS選擇器計算出節(jié)點的樣式,創(chuàng)建另一個樹 —- 渲染樹。
3、布局渲染樹(Layout of the render tree): 從根節(jié)點遞歸調(diào)用,計算每一個元素的大小、位置等,給每個節(jié)點所應(yīng)該出現(xiàn)在屏幕上的精確坐標(biāo)。
4、繪制渲染樹(Painting the render tree) : 遍歷渲染樹,每個節(jié)點將使用UI后端層來繪制。
主要的流程就是:構(gòu)建一個dom樹,頁面要顯示的各元素都會創(chuàng)建到這個dom樹當(dāng)中,每當(dāng)一個新元素加入到這個dom樹當(dāng)中,瀏覽器便會通過css引擎查遍css樣式表,找到符合該元素的樣式規(guī)則應(yīng)用到這個元素上。
注意了:css引擎查找樣式表,對每條規(guī)則都按從右到左的順序去匹配。 看如下規(guī)則:
#nav li {}
看起來很快,實際上很慢,盡管這讓人有點費解。我們中的大多數(shù)人,尤其是那些從左到右閱讀的人,可能猜想瀏覽器也是執(zhí)行從左到右匹配規(guī)則的,因此會推測這條規(guī)則的開銷并不高。在腦海中,我們想象瀏覽器會像這樣工作:找到唯一的ID為nav的元素,然后把這個樣式應(yīng)用到直系子元素的li元素上。我們知道有一個ID為nav的元素,并且它只有幾個Li子元素,所以這個CSS選擇符應(yīng)該相當(dāng)高效。
事實上,CSS選擇符是從右到左進行匹配的。了解這方面的知識后,我們知道這個之前看似高效地規(guī)則實際開銷相當(dāng)高,瀏覽器必須遍歷頁面上每個li元素并確定其父元素的id是否為nav。
*{}
額,這種方法我剛寫CSS的也寫過,殊不知這種效率是差到極點的做法,因為*通配符將匹配所有元素,所以瀏覽器必須去遍歷每一個元素,這樣的計算次數(shù)可能是上萬次!
ul#nav{} ul.nav{}
在頁面中一個指定的ID只能對應(yīng)一個元素,所以沒有必要添加額外的限定符,而且這會使它更低效。同時也不要用具體的標(biāo)簽限定類選擇符,而是要根據(jù)實際的情況對類名進行擴展。例如把ul.nav改成.main_nav更好。
ul li li li .nav_item{}
對于這樣的選擇器,之前也寫過,最后自己也數(shù)不過來有多少后代選擇器了,何不用一個類來關(guān)聯(lián)最后的標(biāo)簽元素,如.extra_navitem,這樣只需要匹配class為extra_navitem的元素,效率明顯提升了
對此,在CSS書寫過程中,總結(jié)出如下性能提升的方案:
1.避免使用通配規(guī)則 如 *{} 計算次數(shù)驚人!只對需要用到的元素進行選擇
2.盡量少的去對標(biāo)簽進行選擇,而是用class 如:#nav li{},可以為li加上nav_item的類名,如下選擇.nav_item{}
3.不要去用標(biāo)簽限定ID或者類選擇符 如:ul#nav,應(yīng)該簡化為#nav
4.盡量少的去使用后代選擇器,降低選擇器的權(quán)重值 后代選擇器的開銷是最高的,盡量將選擇器的深度降到最低,最高不要超過三層,更多的使用類來關(guān)聯(lián)每一個標(biāo)簽元素
5.考慮繼承 了解哪些屬性是可以通過繼承而來的,然后避免對這些屬性重復(fù)指定規(guī)則
選用高效的選擇符,可以減少頁面的渲染時間,從而有效的提升用戶體驗(頁面越快,用戶當(dāng)然越喜歡_),你可以看一下CSS selectors Test,這個實驗的重點是評估復(fù)雜選擇符和簡單選擇符的開銷。也許當(dāng)你想讓渲染速度最高效時,你可能會給每個獨立的標(biāo)簽配置一個ID,然后用這些ID寫樣式。那的確會超級快,也超級荒唐!這樣的結(jié)果是語義極差,后期的維護難到了極點。
但說到底,CSS性能這東西對于小的項目來講可能真的是微乎其微的東西,提升可能也不是很明顯,但對于大型的項目肯定是有幫助的。而且一個好的CSS書寫習(xí)慣和方式能夠幫助我們更加嚴(yán)謹(jǐn)?shù)囊笞约骸?/p>
結(jié)語
能看到這里,你才是賺到了。上面BB了那么多,想必客官一定看得頭暈霧繞了。大家心里一定有個疑問,瀏覽器兼容性有這么惡心人嗎?有沒有一個好的解決方案呢?答案是一定的,那就是框架,各種各樣的框架。
啥是框架?
框架從本質(zhì)上來說,就是幫你干活,讓你少操心,什么兼容性了、底層的東西了統(tǒng)統(tǒng)交給我。你只需要告訴我你要干嘛,我全幫你搞定了。當(dāng)然了,幫你搞定兼容性也是有代價的,那就是犧牲性能換兼容性。不過在這個硬件過剩的時代,使用框架所消耗掉的那點性能絕對是可以接受的,反正我相信大家肯定不愿意天天被測試追著問 "xxx,IE下又白屏了,IE下又沒居中了,IE下樣式又亂掉了...."。嗯,筆者對 IE 絕對沒(shen)有(wu)成(tong)見(jue).
關(guān)于框架怎么用?且聽下回分解~