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