摘要:結(jié)論就結(jié)論而言,強(qiáng)烈建議使用標(biāo)簽,慎用方式。這樣可以避免考慮的語(yǔ)法規(guī)則和注意事項(xiàng),避免產(chǎn)生資源文件下載順序混亂和請(qǐng)求過(guò)多的煩惱。區(qū)別從屬關(guān)系區(qū)別是提供的語(yǔ)法規(guī)則,只有導(dǎo)入樣式表的作用是提供的標(biāo)簽,不僅可以加載文件,還可以定義連接屬性等。
我們都知道,外部引入 CSS 有2種方式,link標(biāo)簽和@import。
它們有何本質(zhì)區(qū)別,有何使用建議,在考察外部引入 CSS 這部分內(nèi)容時(shí),經(jīng)常被提起。
如今,很多學(xué)者本著知其然不欲知其所以然的學(xué)習(xí)態(tài)度,不求甚解,只求結(jié)論。
所以,本文遵循 css hack 的漸進(jìn)識(shí)別原則,
結(jié)論 → 區(qū)別 → 爭(zhēng)議 → 細(xì)節(jié) → 祖墳 → 感想,逐漸加深理論層級(jí),
力爭(zhēng)每個(gè) level 的讀者,都能 get 到自己想要的內(nèi)容,不必繼續(xù)閱讀下去。
就結(jié)論而言,強(qiáng)烈建議使用link標(biāo)簽,慎用@import方式。
這樣可以避免考慮@import的語(yǔ)法規(guī)則和注意事項(xiàng),避免產(chǎn)生資源文件下載順序混亂和http請(qǐng)求過(guò)多的煩惱。
1.從屬關(guān)系區(qū)別
@import是 CSS 提供的語(yǔ)法規(guī)則,只有導(dǎo)入樣式表的作用;link是HTML提供的標(biāo)簽,不僅可以加載 CSS 文件,還可以定義 RSS、rel 連接屬性等。
2.加載順序區(qū)別
加載頁(yè)面時(shí),link標(biāo)簽引入的 CSS 被同時(shí)加載;@import引入的 CSS 將在頁(yè)面加載完畢后被加載。
3.兼容性區(qū)別
@import是 CSS2.1 才有的語(yǔ)法,故只可在 IE5+ 才能識(shí)別;link標(biāo)簽作為 HTML 元素,不存在兼容性問(wèn)題。
4.DOM可控性區(qū)別
可以通過(guò) JS 操作 DOM ,插入link標(biāo)簽來(lái)改變樣式;由于 DOM 方法是基于文檔的,無(wú)法使用@import的方式插入樣式。
5.權(quán)重區(qū)別(該項(xiàng)有爭(zhēng)議,下文將詳解)
link引入的樣式權(quán)重大于@import引入的樣式。
不知從什么時(shí)候開(kāi)始,當(dāng)你在網(wǎng)上搜索link和@import的區(qū)別時(shí),千篇一律的答案里就悄悄的多了一句“link引入的樣式權(quán)重大于@import引入的樣式”。
但是并沒(méi)有一份答案,附帶著對(duì)這句話的任何解釋或?qū)嵗?/p>
這句話究竟是什么意思,該怎么理解呢?
發(fā)揚(yáng)探索精神,我們不妨繼續(xù)查閱資料。后來(lái)發(fā)現(xiàn),還是有不少文章和帖子,對(duì)這句話表示質(zhì)疑,進(jìn)而自己寫(xiě)了 demo 去驗(yàn)證,驗(yàn)證的結(jié)果,確實(shí)無(wú)法與這句話相吻合。
而且,筆者也并未發(fā)現(xiàn)能清楚、正確、有理有據(jù)的解釋這個(gè)結(jié)論到底對(duì),還是不對(duì)的文章。
那么這個(gè)結(jié)論,最初是從哪里來(lái)的,可能已經(jīng)無(wú)從考證了。
換個(gè)思維方式,不去爭(zhēng)辯它的對(duì)錯(cuò)了,探索未果,我們就從這個(gè)結(jié)論的核心關(guān)鍵詞“權(quán)重”出發(fā),去研究它。
說(shuō)到“權(quán)重”,有必要再解釋一下:CSS 中的權(quán)重,指的是選擇器的優(yōu)先級(jí)。
CSS 選擇器的權(quán)重高,即選擇器的優(yōu)先級(jí)高。
CSS 的優(yōu)先級(jí)特性表現(xiàn)為,對(duì)同一 HTML 元素設(shè)置樣式時(shí),不同選擇器的優(yōu)先級(jí)不同,優(yōu)先級(jí)低的樣式將被高優(yōu)先級(jí)的樣式層疊掉。
CSS 權(quán)重優(yōu)先級(jí)順序簡(jiǎn)單表示為:
!important > 行內(nèi)樣式 > ID > 類、偽類、屬性 > 標(biāo)簽名 > 繼承 > 通配符
為了便于理解權(quán)重的計(jì)算方式,我們按以下方式進(jìn)行數(shù)值假設(shè)分析:
選擇器 | 權(quán)重 |
---|---|
通配符 | 0 |
標(biāo)簽 | 1 |
類/偽類/屬性 | 10 |
ID | 100 |
行內(nèi)樣式 | 1000 |
important | 1/0(無(wú)窮大) |
再舉實(shí)例:
Document
每個(gè)樣式的權(quán)重值,都在實(shí)例中,以注釋的形式標(biāo)明。
根據(jù)權(quán)重值可知,最終,這個(gè)按鈕的樣式一定是,藍(lán)色背景,白色字,結(jié)果如下圖:
存在!important時(shí),不作他想,一定是權(quán)重最大的樣式。
既然我們了解了,CSS 中的權(quán)重是怎么回事,那回到主題,“link引入的樣式權(quán)重大于@import引入的樣式”,
難道 CSS 的引入方式也有權(quán)重嗎?其實(shí)我們不必糾結(jié)它是否有權(quán)重之說(shuō),我們只需理論結(jié)合實(shí)際的去分析,各種情況下,結(jié)果如何即可。
現(xiàn)有如下3個(gè)css文件:
/* green.css */ div { background-color: green; border: 3px solid red; } /* yellow.css */ div { background-color: yellow; border: 3px solid black; } /* blue.css */ @import url("green.css"); div{ background-color: blue; }
實(shí)例1:
Document
實(shí)例1結(jié)果如下圖:
實(shí)例2:
Document
實(shí)例2結(jié)果如下圖:
對(duì)比實(shí)例1和實(shí)例2這兩個(gè)正好相反的結(jié)果可知,link和@import并沒(méi)有產(chǎn)生類似權(quán)重的效果,只是單純的體現(xiàn)了CSS的層疊性,寫(xiě)在后面的樣式,覆蓋前面的樣式。
實(shí)例3:
Document
實(shí)例3結(jié)果如下圖:
實(shí)例4:
Document
實(shí)例4結(jié)果如下圖:
分析實(shí)例3和實(shí)例4的結(jié)果可知:
對(duì)于實(shí)例3,我們看到紅色邊框,證明內(nèi)聯(lián)樣式中使用@import引入的green.css已經(jīng)生效,但其背景樣式被內(nèi)聯(lián)樣式中的粉色背景層疊掉,這個(gè)現(xiàn)象表明,@import不只是如我們看到的那樣,處于內(nèi)聯(lián)樣式頂部,其被引入的樣式,在結(jié)構(gòu)上,也確實(shí)是被置于內(nèi)聯(lián)樣式之前,所以內(nèi)聯(lián)樣式才能夠?qū)盈B掉它。
同理,實(shí)例4中,在link標(biāo)簽引入的blue.css文件內(nèi),頂部同樣存在@import引入的green.css,紅色邊框依然可以證明,green.css已經(jīng)生效,但其背景樣式被blue.css本身的藍(lán)色背景層疊掉,@import引入的樣式在blue.css中也是被置于它本身樣式之前的。
到此為止,我展開(kāi)了大膽的猜想,“link引入的樣式權(quán)重大于@import引入的樣式”,這個(gè)結(jié)論的給出者,是想告訴大家:
在link標(biāo)簽引入的 CSS 文件中,使用@import時(shí)需注意,如果已經(jīng)存在相同樣式,@import引入的這個(gè)樣式將被該 CSS 文件本身的樣式層疊掉,表現(xiàn)出link標(biāo)簽引入的樣式權(quán)重大于@import引入的樣式這樣的直觀效果。
對(duì)于我設(shè)想的結(jié)論,似乎挺能說(shuō)通的,畢竟這是實(shí)踐出的結(jié)果。
那些驗(yàn)證過(guò)此結(jié)論的前人,他們都是在一個(gè) HTML 頁(yè)面中,一前一后分別使用link和內(nèi)聯(lián)樣式的@import去比較的,我在實(shí)例1和實(shí)例2中也是如此做的,并不能反推出“link引入的樣式權(quán)重大于@import引入的樣式”這個(gè)結(jié)論,所以,我不自量力的認(rèn)為,這個(gè)結(jié)論其實(shí)最初只是丟了個(gè)已知條件而已。
那么我們一起把這個(gè)結(jié)論重新梳理一下:在link標(biāo)簽引入的 CSS 文件中使用@import時(shí),相同樣式將被該 CSS 文件本身的樣式層疊。
Ps.首先感謝各種看官的閱讀。筆者屬于學(xué)習(xí)階段,學(xué)識(shí)尚淺,雖然本文結(jié)論已得到筆者編碼驗(yàn)證,但不排除筆者大腦短路、措辭有誤的可能,有緣閱讀到此處的都是真愛(ài),希望諸位大拿、大牛、大仙、大圣、大神們不吝賜教,及時(shí)指正,避免誘導(dǎo)萌新誤入歧途,再次向你們表達(dá)筆者的謝意!
細(xì)節(jié)既然已經(jīng)說(shuō)了這么多,就順便提一下關(guān)于@import使用時(shí)的其它細(xì)節(jié)。
在《CSS權(quán)威指南》中寫(xiě)道:
@import一定要寫(xiě)在除@charset外的其他任何 CSS 規(guī)則之前,如果置于其它位置將會(huì)被瀏覽器忽略,而且,在@import之后如果存在其它樣式,則@import之后的分號(hào)是必須書(shū)寫(xiě),不可省略的。
到此為止,似乎事情都弄清楚了,但是突然又有個(gè)疑點(diǎn)浮現(xiàn)出來(lái):
在討論區(qū)別的時(shí)候,不是說(shuō)加載頁(yè)面時(shí),link標(biāo)簽引入的 CSS 先于@import引入的 CSS 加載嗎,那link標(biāo)簽引入的樣式又怎會(huì)把@import引入的樣式層疊掉呢?
要回答這個(gè)問(wèn)題,首先我們要一起明確一些有關(guān)瀏覽器的概念:
瀏覽器執(zhí)行過(guò)程可以簡(jiǎn)單分為加載、解析、渲染,這三個(gè)步驟。
加載:根據(jù)請(qǐng)求的URL進(jìn)行域名解析,向服務(wù)器發(fā)送請(qǐng)求,接收響應(yīng)文件(如 HTML、JS、CSS、圖片等)。
解析:對(duì)加載到的資源(HTML、JS、CSS等)進(jìn)行語(yǔ)法解析,構(gòu)建相應(yīng)的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(比如HTML的DOM樹(shù),JS對(duì)象的屬性表,CSS的樣式規(guī)則等)。
渲染:構(gòu)建渲染樹(shù),對(duì)各個(gè)元素進(jìn)行位置計(jì)算、樣式計(jì)算等,然后根據(jù)渲染樹(shù)完成頁(yè)面布局及繪制的過(guò)程(可以理解為“畫(huà)”頁(yè)面元素)。
這幾個(gè)過(guò)程不是完全孤立的,會(huì)有交叉,比如HTML加載后就會(huì)進(jìn)行解析,然后拉取HTML中指定的CSS、JS等。`
現(xiàn)在,我們應(yīng)該已經(jīng)了解了加載和渲染的概念,明白它們是兩個(gè)不同的過(guò)程,那么對(duì)上文中拋出的疑問(wèn)繼續(xù)追問(wèn):
link先于@import加載,是不是也先于@import渲染呢?
實(shí)際上,渲染的動(dòng)作一般都會(huì)執(zhí)行多次,最后一次渲染,一定是依據(jù)之前加載過(guò)的所有樣式整合后的渲染樹(shù)進(jìn)行繪制頁(yè)面的,已經(jīng)被渲染過(guò)的頁(yè)面元素,也會(huì)被重新渲染。
那么我們就可以把@import這種導(dǎo)入 CSS 文件的方式理解成一種替換,CSS 解析引擎在對(duì)一個(gè) CSS 文件進(jìn)行解析時(shí),如在文件頂部遇到@import,將被替換為該@import導(dǎo)入的 CSS 文件中的全部樣式。
峰回路轉(zhuǎn),柳暗花明,終于弄明白為何@import引入的樣式,會(huì)被層疊掉了。其雖然后被加載,卻會(huì)在加載完畢后置于樣式表頂部,最終渲染時(shí)自然會(huì)被下面的同名樣式層疊。
至此為止,“link引入的樣式權(quán)重大于@import引入的樣式”這個(gè)結(jié)論,我終于為它圓了場(chǎng)。但愿此結(jié)論的作者,本意真如我的猜測(cè),否則若是我多心而跑偏了的話,不敢想象這背后究竟隱藏著多大的秘密。
祖墳有些細(xì)心而專業(yè)的讀者可能已經(jīng)發(fā)現(xiàn)了,我用自己的思路和措辭,粗略的解釋了有關(guān) CSS 加載和渲染的知識(shí),有些涉世未深的前端愛(ài)好者可能會(huì)一頭霧水,無(wú)法作為系統(tǒng)學(xué)習(xí)的依據(jù)。這不打緊,出來(lái)混,祖墳總是要刨的,想要透徹的學(xué)習(xí)相關(guān)內(nèi)容,進(jìn)一步了解底層原理的學(xué)者,我早已為你備下了豐厚的見(jiàn)面禮~
有關(guān)link和@import在性能分析方面的比較,國(guó)外的高手早在多年前就曾執(zhí)過(guò)筆:
愛(ài)好母語(yǔ)的請(qǐng)戳我:https://www.stevesouders.com/blog/2009/04/09/dont-use-import/
閱讀英語(yǔ)的請(qǐng)戳我:https://www.qianduan.net/high-performance-web-site-do-not-use-import/
有關(guān)瀏覽器內(nèi)部工作原理的神作,也是幾年前出自歪果仁大牛:
1 為普通話:https://kb.cnblogs.com/page/129756/
2 for English:http://taligarsiel.com/Projects/howbrowserswork1.htm
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://hztianpu.com/yun/96789.html
摘要:結(jié)論就結(jié)論而言,強(qiáng)烈建議使用標(biāo)簽,慎用方式。這樣可以避免考慮的語(yǔ)法規(guī)則和注意事項(xiàng),避免產(chǎn)生資源文件下載順序混亂和請(qǐng)求過(guò)多的煩惱。區(qū)別從屬關(guān)系區(qū)別是提供的語(yǔ)法規(guī)則,只有導(dǎo)入樣式表的作用是提供的標(biāo)簽,不僅可以加載文件,還可以定義連接屬性等。 我們都知道,外部引入 CSS 有2種方式,link標(biāo)簽和@import。它們有何本質(zhì)區(qū)別,有何使用建議,在考察外部引入 CSS 這部分內(nèi)容時(shí),經(jīng)常被提...
摘要:瀏覽器端使用的和集成使用時(shí)會(huì)用到中路由分類基于提供的和事件來(lái)保持和的同步。路由剖析在上面的示例中是轉(zhuǎn)發(fā)的樞紐在這個(gè)中轉(zhuǎn)站有很多線路通過(guò)開(kāi)關(guān)可以啟動(dòng)列車(chē)的運(yùn)行乘坐列車(chē)就可以發(fā)現(xiàn)新大陸。 引言 在使用react做復(fù)雜的spa開(kāi)發(fā)中,開(kāi)發(fā)中必不可少的就是react-router,它使用Lerna管理多個(gè)倉(cāng)庫(kù), 在browser端常使用的幾個(gè)如下所示 react-router 提供了路由的...
摘要:一概念通常的程序的構(gòu)架是指將一個(gè)程序分割為源代碼文件的集合以及將這些部分連接在一起的方法。的程序構(gòu)架可表示為一個(gè)程序就是一個(gè)模塊的系統(tǒng)。它有一個(gè)頂層文件啟動(dòng)后可運(yùn)行程序以及多個(gè)模塊文件用來(lái)導(dǎo)入工具庫(kù)。導(dǎo)入是中程序結(jié)構(gòu)的重點(diǎn)所在。 一、概念 通常的Python程序的構(gòu)架是指:將一個(gè)程序分割為源代碼文件的集合以及將這些部分連接在一起的方法。 Python的程序構(gòu)架可表示為: showImg...
摘要:獲取資源失敗,將該線程加入等待隊(duì)列尾部,標(biāo)記為獨(dú)占模式。如果有剩余資源則會(huì)喚醒下一個(gè)線程,且整個(gè)過(guò)程忽略中斷的影響。 AQS概念及定義 ASQ:AbstractQueuedSynchronizer 它維護(hù)了一個(gè)volatile int state(代表共享資源)和一個(gè)FIFO線程等待隊(duì)列(多線程爭(zhēng)用資源被阻塞時(shí)會(huì)進(jìn)入此隊(duì)列,有個(gè)內(nèi)部類Node定義了節(jié)點(diǎn)。隊(duì)列由AQS的volatile成...
閱讀 3094·2021-11-23 09:51
閱讀 1740·2021-10-15 09:39
閱讀 1144·2021-08-03 14:03
閱讀 2987·2019-08-30 15:53
閱讀 3511·2019-08-30 15:52
閱讀 2584·2019-08-29 16:17
閱讀 2921·2019-08-29 16:12
閱讀 1727·2019-08-29 15:26