【转】刨根究底CSS(1):开篇
01 一道小菜
CSS很難,這應該是絕大多數Web開發人員的共識。
什么?你并不覺得很難?那我就先上一道小菜,請君品嘗。
這是個乍一看,讓人覺得很詭異的案例……
算了,本來想滔滔不絕介紹一番,但一想到Linux之父Linus大神所說的“Talk is cheap, show me the code.”,那我還是“廢話少說,放碼過來”吧,各位接招。
HTML部分:
<p>ABC XYZ</p> <div><span>abc xyz</span> </div> <p>ABC XYZ</p>CSS部分:
p {width: 200px; margin: 0; background: silver; } div {width: 200px;line-height: 0;font-size: 50px;background: gold; } span {font-size: 0; }這個案例的“詭異”之處在于,當子元素span的font-size屬性值為0,因而其高度也為0時,竟然撐開了父元素div的高度。如下面的圖所示。
而當子元素span的font-size屬性值不為0,因而其高度也不為0時,比如刪除子元素的font-size屬性,這種情況下span元素的font-size屬性值默認繼承自父元素div,為50px,其他則完全不變,反而沒有撐開父元素div的高度。如下面的圖所示。
這也太反常,太違反直覺了吧?難道是瀏覽器有bug?
但在主流瀏覽器中,Chrome、FireFox、Edge、Opera都一樣,甚至連IE8都一樣,貌似就Safari不同(考慮到Safari已經淪落為了新一代的IE,這倒也不奇怪)。
好,坑先挖到這里,各位慢慢爬坑,期待各位的爬坑報告。
?
02 CSS難在哪里
很多前端初學者,通常一開始對CSS都很不以為然,以為看看w3school,頂多再讀一兩本專著(比如《CSS權威指南》、《精通CSS》之類的),就一定不在話下了。
但是,剛開始這樣想的人,逐漸地一定會被慘淡的事實教育得重新做人,最終身心備受打擊,嚴重的甚至于開始懷疑人生[流汗]
先一起來觀摩一下知乎里的這些問題:
CSS真有這么難?
我覺得主要原因在于,重視不足,說白了就是一開始太小看CSS了。
也確實,說CSS是一種計算機語言都非常勉強,不就是對HTML元素設置一些樣式屬性嘛。
然而,CSS表面的看似簡單,掩蓋了由于歷史原因所造成的問題:屬性之間互相影響的情況非常嚴重;這用軟件工程的術語來說,就是屬性之間耦合得非常嚴重,這是CSS復雜性的根源。
所謂“歷史原因”,主要應該是由于預估不足、發展太快所導致的。
一開始想得比較簡單,不就相當于將報紙雜志搬到網絡上嗎?無非是多了可以跳轉的鏈接,本質上還是圖文排版啊。
但隨著互聯網的迅猛發展,Web頁面所承載的內容越來越復雜,其功能要求也越來越豐富,僅僅圖文排版是搞不定了,于是在原來的基礎上加各種功能。
結果就是,CSS屬性不斷增長膨脹,而為了保持向下兼容,卻又只能在原來的基礎上修修補補,沒辦法推倒重來。
這就好比一個小孩的衣服,隨著小孩身體的不斷瘋長,功能要求也越來越高,既要保暖,又要護體,還要審美,但卻又不能扔掉重做,只能在原來的基礎上不斷地修改,不斷地一層層打補丁......
想想這個難度,想想這件衣服結果會怎樣?
因此,實踐中,當你時不時被屬性之間鬼畜般的相互影響搞得茫然無措、筋疲力盡時,如果能想到這一層,就能多一分理解,多一分冷靜。
?
03 磨刀不誤砍柴工
當然,光有理解和冷靜,是無法解決問題的。
但在這些寶貴的理解和冷靜的基礎上,“磨刀不誤砍柴工”,花點時間,深入了解CSS的底層原理、運作機制和歷史沿革,你一定會不斷地發出“啊,原來是這樣”的感慨。
之后,不敢說從此就一定順風順水、一馬平川了,但至少會自信很多,會多了一種像是庖丁解牛般盡在掌握的掌控感,進而給你帶來“提刀而立,為之四顧,為之躊躇滿志”的極大滿足感。
事實上,正因為很多人對CSS太過于輕視,學習又不得法,導致所謂“易學難精”的CSS,可以說是成了優秀Web開發人員少有的護城河,因為同等的CSS經驗很難通過同等的編程經驗、工程經驗來換取。
也就是說,就算你寫了多年的代碼,就算你熟練掌握了多門語言,在CSS面前,都得重新刷新自己的認知。
但如果你一旦掌握了CSS的規律和精髓,無疑將脫穎而出、鶴立雞群、茫然四顧、獨孤求敗……好吧,這有點自我膨脹了[捂臉]
因此,CSS值得你花時間。
而且,跟著我的思路,我們一起來刨根究底,相信你可以少走很多彎路,少花很多時間。
?
04 內容說明
這里需要說明一點,本“刨根究底CSS”系列文章,不是針對完全沒有CSS經驗的人而寫的。
因此,在看本系列文章之前,至少得對CSS的基本概念和基礎語法有所了解,最好是還刷過一遍w3school中的入門課程。
而如果你是在實踐中積累了不少困惑,遇到了瓶頸,被CSS虐了千百遍的Web開發人員,那就最適合不過了。
也因此,本“刨根究底CSS”系列文章,不會按照慣常的寫法,逐個對CSS屬性進行介紹,因為這些直接到W3C官網和MDN上查看就可以了,用不著我再復制粘貼一遍。
當然,畢竟是講解CSS的文章,如果完全脫離對CSS屬性的介紹,這文章也就沒法寫了。
只不過,對關鍵CSS屬性的介紹,將穿插在對CSS底層原理和運作機制的說明之中,而不是單純地簡單羅列出來。
總體而言,就是一方面站在瀏覽器的角度,盡量將瀏覽器通過CSS屬性將一個又一個的框框最終繪制出來的過程梳理一遍;另一方面是站在Web開發人員的角度,盡量從實踐中的棘手問題入手,看看到底該怎么來理解問題,又該怎樣來解決問題。
具體來說,站在瀏覽器的角度,Web網頁本質上就是由元素框套著元素框構成的,因此如果要從CSS的底層原理和運行機制層面刨根究底地徹底說透,則必須從視覺格式化模型的角度入手,將以下幾方面的內容講清楚:
1)元素框分類:即元素框主要分為哪幾類,各有什么區別,重點內容包括塊級框、行內級框、匿名框以及其他各種特殊框等。
2)元素框模型:即元素框主要由哪幾個部分構成,重點內容包括內容框、補白框、邊界框、邊距框與box-sizing屬性等。
3)元素框定位:即元素框是如何確定位置的,重點內容將包括視口(布局視口、設備視口、理想視口)、包含塊,以及常規流定位、浮動定位、絕對定位等。
4)元素框大小:即元素框的大小是怎樣計算的,重點內容包括寬度、高度、邊距計算,行高計算,以及垂直對齊(尤其是垂直居中對齊,相信這是很多人的噩夢)、字體與字體度量(這個要徹底講清楚,要死很多腦細胞,但一旦弄懂了,就會有種打通了任督二脈的感覺)等。
注:垂直對齊、字體與字體度量看似與元素框大小的計算無關,但實際上這是嚴重的誤解,這應該是CSS最難的部分,也是讓Web開發者最為抓狂的部分。
5)元素框關系:即元素框相互之間的關系(一般也稱之為布局關系)是怎么處理的,重點內容包括元素框與其祖先框、后代框以及同級兄弟框之間的關系處理,其中關鍵在于理解邊距折疊、層疊上下文、格式化上下文FC以及各種格式化上下文與其所在的包含塊之間的關系。
注:格式化上下文FC,包括塊格式化上下文BFC、行內格式化上下文IFC、表格格式化上下文TFC、彈性格式化上下文FFC、網格格式化上下文GFC等。
這樣一梳理,就可以發現,只要緊緊抓住元素框的生成與繪制這條主線,就能高屋建瓴、綱舉目張,將以往覺得零零碎碎、雜七雜八、不成體系的各種CSS屬性和奇技淫巧貫通起來,從而理解起來圓融無礙、如環無端。
當然,若只是站在瀏覽器的角度,將底層原理和運行機制理解得通透徹底,雖然可以獲得大局觀,理解也更為體系化,但這也還是不足夠的。
還應站在Web開發人員的角度,從解決實踐中的棘手問題入手,從而使用起來得心應手、順手拈來。這就必須從CSS工程化的角度入手,將以下幾方面的內容講清楚:
1)層疊規則;
2)選擇器及其權重計算與優先規則;
3)命名空間;
4)模塊化;
5)預處理與后處理;
6)媒體類型與媒體查詢;
7)度量單位與值;
8)偽元素與偽類;
9)變量與函數;
10)文本排版;
11)布局設計(浮動布局、流式布局、彈性布局、網格布局、響應式布局等);
12)針對Retina顯示屏的特殊適配;
13)書寫規范;
14)CSS Lint;
15)性能優化。
以上兩個角度方面的內容,顯然是不可能絕對分開的。因此,這兩方面的內容將會互相穿插來講。
不過,前期會主要從瀏覽器角度來講解,同時穿插少部分涉及從Web開發者角度來講解的內容;后期會主要從Web開發者角度來講解,同時穿插少部分涉及從瀏覽器角度來講解的內容。
?
05 CSS級別
由于前面說了這么多,已經占了不少篇幅,接下來暫時不說其他內容,先簡單說一下CSS級別。
記得有一次,有個同事問我:“JavaScript有ES5、ES6、ES7、ES8等不斷升級的版本,CSS為什么只有CSS2、CSS3,卻沒再聽說有CSS4、CSS5等升級版本呢?”
這確實是個有意思的問題。CSS在對待版本的問題上,很有些“特立獨行”。
事實上,CSS目前不使用傳統意義上的版本來進行區分,而是使用級別來進行區分。
每一級別CSS都建立在前一級別的基礎上,改進了定義并添加了特性。每個較高級別的特性集是任何較低級別的超集,并且較高級別的特性集所允許的行為是較低級別所允許的行為的子集。
因此,符合較高級別的CSS的用戶代理也符合所有較低級別的CSS。
?
05.01 CSS級別1(CSS Level 1)
由于CSS 1規范已被W3C的CSS工作組(CSS Working Group)認定為已過時,因此,CSS級別1被確定為:CSS 1規范中所定義的所有特性(包括屬性、值、at-Rule等),但這些特性的語法和規則等則以CSS 2.1規范中的為準。
注:CSS1規范在早期相當于是CSS 1.0版,CSS 2、CSS 2.1與之類似,在早期相當于是CSS 2.0版和CSS2.1版。隨著CSS引入級別的概念之后,級別可以是跨規范的,并且逐漸淡化并最終棄用了版本的概念。
另外,sytle屬性規范定義了特定元素的style屬性中的CSS樣式所應遵循的規范。
注:
所謂style屬性,即元素的style屬性,其中所書寫的CSS樣式,被稱為行內樣式(inline style),也稱為行間樣式,比如:<p style="color: red; font-size: 20px;...">...</p>,p元素的sytle屬性中所定義的“color:red; font-size: 20px; ...”樣式,就是這里所說的style屬性樣式。
style屬性規范主要規定了style屬性中的CSS樣式與常規的CSS樣式在一致性上的要求,以及在層疊計算時的優先規則等等。
?
05.02 CSS級別2(CSS Level 2)
雖然從技術上講,CSS 2規范是W3C推薦標準,但它在W3C定義其為候選推薦階段之前,就已經進入了推薦階段。
注:
候選推薦階段為推薦階段的前一個階段。
注意,W3C組織作為一個國際性的互聯網技術協作組織,只有標準的推薦建議權,并沒有標準的強制執行權,所以即便是該組織所制定的正式規范也只是稱之為推薦標準,不過目前幾乎所有主流瀏覽器都基本上遵循了這些推薦標準。
之前微軟的IE瀏覽器有很多就沒有遵循W3C標準,而是自搞一套,后來IE也就因此而被逐漸邊緣化了,所以最后連微軟自己都只好放棄了IE,而重新開發了遵循W3C標準的Edge瀏覽器。
現在蘋果的Safari瀏覽器又有步IE瀏覽器后塵的趨勢,被很多Web開發者戲稱為“新一代的IE”。
隨著時間的推移、實踐檢驗和進一步審查,暴露了CSS 2規范中的許多問題,因此CSS工作組沒有繼續擴展已經很龐大的勘誤表,而是選擇了定義CSS Level 2 Revision 1(CSS 2.1)。如果CSS 2與CSS 2.1這兩個規范之間有任何沖突,應以CSS 2.1為準。
一旦CSS 2.1成為候選推薦標準,即便不是處于和CSS 2相同的正式穩定階段(CSS 2已經是推薦標準),但實際上就有效取代了CSS 2推薦標準。CSS 2中的功能如果在CSS 2.1中被刪除了,則應視為處于“候選推薦”階段。
但請注意,其中許多功能已經或將被納入CSS級別3工作草案中。如果CSS級別3達到候選推薦階段,那么CSS 2中的定義就過時了。
CSS 2.1規范定義了CSS級別2,而style屬性規范則定義了特定元素的style屬性中的樣式所應遵循的規范。
?
05.03 CSS級別3(CSS Level 3)
CSS級別3是在CSS級別2之上,一個模塊一個模塊地單獨構建的,使用CSS 2.1規范作為其核心。每個模塊添加功能和/或替換部分CSS 2.1規范。
CSS工作組希望新的CSS模塊只是添加功能并改進定義,而不會與CSS 2.1規范相沖突。當每個模塊完成后,它將插入到現有的CSS 2.1系統以及之前已完成的模塊中。
從這個級別開始,模塊被獨立地分級別定義。例如,選擇器級別4(Selectors Level 4)很可能在CSS行模塊級別3(CSS Line Module Level 3)之前完成。
CSS級別2中不存在的模塊(即沒有等效項的模塊),從級別1開始;CSS級別2中已存在的模塊,其更新從級別3開始。
05.04 CSS級別4及以上級別(CSS Level 4 and beyond)
沒有CSS級別4和以上級別。獨立的模塊可以單獨地達到級別4或更高級別,但整體的CSS語言不再有級別4。因此稱為CSS級別4或CSS 4都是不正確的。
實際上,“CSS級別3”作為一個術語,也僅用于將其與以前的“CSS級別1”和“CSS級別2”這樣的單一整體級別區分開來,而并非真的存在這么一個CSS語言的單一整體級別。
?
(未完待續)
總結
以上是生活随笔為你收集整理的【转】刨根究底CSS(1):开篇的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 动力电池回收再利用 奥迪推出电动“三蹦子
- 下一篇: 【转】C#数据结构-有限状态机