咱們都知道,外部引入 CSS 有2種方式,link
標籤和@import
。
它們有何本質區別,有何使用建議,在考察外部引入 CSS 這部份內容時,常常被提起。css
現在,不少學者本着知其然不欲知其因此然的學習態度,不求甚解,只求結論。
因此,本文遵循 css hack 的漸進識別原則,
結論 → 區別 → 爭議 → 細節 → 祖墳 → 感想,逐漸加深理論層級,
力爭每一個 level 的讀者,都能 get 到本身想要的內容,沒必要繼續閱讀下去。html
就結論而言,強烈建議使用link
標籤,慎用@import
方式。
這樣能夠避免考慮@import
的語法規則和注意事項,避免產生資源文件下載順序混亂和http請求過多的煩惱。前端
1.從屬關係區別@import
是 CSS 提供的語法規則,只有導入樣式表的做用;link
是HTML提供的標籤,不只能夠加載 CSS 文件,還能夠定義 RSS、rel 鏈接屬性等。web
2.加載順序區別
加載頁面時,link
標籤引入的 CSS 被同時加載;@import
引入的 CSS 將在頁面加載完畢後被加載。瀏覽器
3.兼容性區別@import
是 CSS2.1 纔有的語法,故只可在 IE5+ 才能識別;link
標籤做爲 HTML 元素,不存在兼容性問題。服務器
4.DOM可控性區別
能夠經過 JS 操做 DOM ,插入link
標籤來改變樣式;因爲 DOM 方法是基於文檔的,沒法使用@import
的方式插入樣式。數據結構
5.權重區別(該項有爭議,下文將詳解)link
引入的樣式權重大於@import
引入的樣式。佈局
不知從何時開始,當你在網上搜索link
和@import
的區別時,千篇一概的答案裏就悄悄的多了一句「link
引入的樣式權重大於@import
引入的樣式」。
可是並無一份答案,附帶着對這句話的任何解釋或實例。性能
這句話到底是什麼意思,該怎麼理解呢?學習
發揚探索精神,咱們不妨繼續查閱資料。後來發現,仍是有很多文章和帖子,對這句話表示質疑,進而本身寫了 demo 去驗證,驗證的結果,確實沒法與這句話相吻合。
並且,筆者也並未發現能清楚、正確、有理有據的解釋這個結論到底對,仍是不對的文章。
那麼這個結論,最初是從哪裏來的,可能已經無從考證了。
換個思惟方式,不去爭辯它的對錯了,探索未果,咱們就從這個結論的核心關鍵詞「權重」出發,去研究它。
說到「權重」,有必要再解釋一下:CSS 中的權重,指的是選擇器的優先級。
CSS 選擇器的權重高,即選擇器的優先級高。
CSS 的優先級特性表現爲,對同一 HTML 元素設置樣式時,不一樣選擇器的優先級不一樣,優先級低的樣式將被高優先級的樣式層疊掉。
CSS 權重優先級順序簡單表示爲:!important > 行內樣式 > ID > 類、僞類、屬性 > 標籤名 > 繼承 > 通配符
爲了便於理解權重的計算方式,咱們按如下方式進行數值假設分析:
選擇器 | 權重 |
---|---|
通配符 | 0 |
標籤 | 1 |
類/僞類/屬性 | 10 |
ID | 100 |
行內樣式 | 1000 |
important | 1/0(無窮大) |
再舉實例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> #myid { /* id選擇器權重爲100 */ background-color: pink; } #divid .myspan input { /* 權重爲 100 + 10 + 1 = 111 */ background-color: yellow; } input[type="button"] { /* 權重爲 10 */ color: white !important; /* !important權重爲無窮大 */ } input.myclass { /* 此爲標籤指定式選擇器,權重爲 1 + 10 = 11 */ color: black; } </style> </head> <body> <div id="divid"> <span class="myspan"> <input type="button" id="myid" class="myclass" name="myname" value="點我" style=" color: green;"> <!-- style樣式的權重爲1000 --> </span> </div> </body> </html>
每一個樣式的權重值,都在實例中,以註釋的形式標明。
根據權重值可知,最終,這個按鈕的樣式必定是,藍色背景,白色字,結果以下圖:
存在!important
時,不做他想,必定是權重最大的樣式。
既然咱們瞭解了,CSS 中的權重是怎麼回事,那回到主題,「link
引入的樣式權重大於@import
引入的樣式」,
難道 CSS 的引入方式也有權重嗎?其實咱們沒必要糾結它是否有權重之說,咱們只需理論結合實際的去分析,各類狀況下,結果如何便可。
現有以下3個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; }
實例1:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 實例1\. link標籤引入yellow.css,內聯樣式引入green.css --> <link rel="stylesheet" href="yellow.css"> <style type="text/css"> @import url("green.css"); </style> </head> <body> <div style="width: 50px; height: 50px;"></div> <!-- 盒子爲,綠色背景,紅色邊框,即green.css生效 --> </body> </html>
實例1結果以下圖:
實例2:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 實例2\. 內聯樣式引入green.css,link標籤引入yellow.css --> <style type="text/css"> @import url("green.css"); </style> <link rel="stylesheet" href="yellow.css"> </head> <body> <div style="width: 50px; height: 50px;"></div> <!-- 盒子爲黃色背景,黑色邊框,即yellow.css生效 --> </body> </html>
實例2結果以下圖:
對比實例1和實例2這兩個正好相反的結果可知,link
和@import
並無產生相似權重的效果,只是單純的體現了CSS的層疊性,寫在後面的樣式,覆蓋前面的樣式。
實例3:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 實例3\. 內聯樣式引入green.css,內聯樣式中設置粉色背景 --> <style type="text/css"> @import url("green.css"); div { background-color: pink; } </style> </head> <body> <div style="width: 50px; height: 50px;"></div> <!-- 盒子爲粉色背景,紅色邊框,即green.css已生效,但背景色被內聯樣式層疊爲粉色 --> </body> </html>
實例3結果以下圖:
實例4:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <!-- 實例4\. link標籤引入blue.css,blue.css中引入green.css --> <link rel="stylesheet" href="blue.css"> </head> <body> <div style="width: 50px; height: 50px;"></div> <!-- 盒子爲藍色背景,紅色邊框,即green.css已生效,但背景色被blue.css層疊爲藍色 --> </body> </html>
實例4結果以下圖:
分析實例3和實例4的結果可知:
對於實例3,咱們看到紅色邊框,證實內聯樣式中使用@import
引入的green.css
已經生效,但其背景樣式被內聯樣式中的粉色背景層疊掉,這個現象代表,@import
不僅是如咱們看到的那樣,處於內聯樣式頂部,其被引入的樣式,在結構上,也確實是被置於內聯樣式以前,因此內聯樣式纔可以層疊掉它。
同理,實例4中,在link
標籤引入的blue.css
文件內,頂部一樣存在@import
引入的green.css
,紅色邊框依然能夠證實,green.css
已經生效,但其背景樣式被blue.css
自己的藍色背景層疊掉,@import
引入的樣式在blue.css
中也是被置於它自己樣式以前的。
到此爲止,我展開了大膽的猜測,「link
引入的樣式權重大於@import
引入的樣式」,這個結論的給出者,是想告訴你們:
在link
標籤引入的 CSS 文件中,使用@import
時需注意,若是已經存在相一樣式,@import
引入的這個樣式將被該 CSS 文件自己的樣式層疊掉,表現出link
標籤引入的樣式權重大於@import
引入的樣式這樣的直觀效果。
對於我設想的結論,彷佛挺能說通的,畢竟這是實踐出的結果。
那些驗證過此結論的前人,他們都是在一個 HTML 頁面中,一前一後分別使用link
和內聯樣式的@import
去比較的,我在實例1和實例2中也是如此作的,並不能反推出「link
引入的樣式權重大於@import
引入的樣式」這個結論,因此,我蚍蜉撼樹的認爲,這個結論其實最初只是丟了個已知條件而已。
那麼咱們一塊兒把這個結論從新梳理一下:在link
標籤引入的 CSS 文件中使用@import
時,相一樣式將被該 CSS 文件自己的樣式層疊。
Ps.首先感謝各類看官的閱讀。筆者屬於學習階段,學識尚淺,雖然本文結論已獲得筆者編碼驗證,但不排除筆者大腦短路、措辭有誤的可能,有緣閱讀到此處的都是真愛,但願諸位大拿、大牛、大仙、大聖、大神們不吝賜教,及時指正,避免誘導萌新誤入歧途,再次向大家表達筆者的謝意!
既然已經說了這麼多,就順便提一下關於@import
使用時的其它細節。
在《CSS權威指南》中寫道:
@import
必定要寫在除@charset
外的其餘任何 CSS 規則以前,若是置於其它位置將會被瀏覽器忽略,並且,在@import
以後若是存在其它樣式,則@import
以後的分號是必須書寫,不可省略的。
到此爲止,彷佛事情都弄清楚了,可是忽然又有個疑點浮現出來:
在討論區別的時候,不是說加載頁面時,link
標籤引入的 CSS 先於@import
引入的 CSS 加載嗎,那link
標籤引入的樣式又怎會把@import
引入的樣式層疊掉呢?
要回答這個問題,首先咱們要一塊兒明確一些有關瀏覽器的概念:
瀏覽器執行過程能夠簡單分爲加載、解析、渲染,這三個步驟。
加載:根據請求的URL進行域名解析,向服務器發送請求,接收響應文件(如 HTML、JS、CSS、圖片等)。
解析:對加載到的資源(HTML、JS、CSS等)進行語法解析,構建相應的內部數據結構(好比HTML的DOM樹,JS對象的屬性表,CSS的樣式規則等)。
渲染:構建渲染樹,對各個元素進行位置計算、樣式計算等,而後根據渲染樹完成頁面佈局及繪製的過程(能夠理解爲「畫」頁面元素)。
這幾個過程不是徹底孤立的,會有交叉,好比HTML加載後就會進行解析,而後拉取HTML中指定的CSS、JS等。`
如今,咱們應該已經瞭解了加載和渲染的概念,明白它們是兩個不一樣的過程,那麼對上文中拋出的疑問繼續追問:
link
先於@import
加載,是否是也先於@import
渲染呢?
實際上,渲染的動做通常都會執行屢次,最後一次渲染,必定是依據以前加載過的全部樣式整合後的渲染樹進行繪製頁面的,已經被渲染過的頁面元素,也會被從新渲染。
那麼咱們就能夠把@import
這種導入 CSS 文件的方式理解成一種替換,CSS 解析引擎在對一個 CSS 文件進行解析時,如在文件頂部遇到@import
,將被替換爲該@import
導入的 CSS 文件中的所有樣式。
峯迴路轉,柳暗花明,終於弄明白爲什麼@import
引入的樣式,會被層疊掉了。其雖而後被加載,卻會在加載完畢後置於樣式表頂部,最終渲染時天然會被下面的同名樣式層疊。
至此爲止,「link
引入的樣式權重大於@import
引入的樣式」這個結論,我終於爲它圓了場。希望此結論的做者,本意真如個人猜想,不然如果我多心而跑偏了的話,不敢想象這背後究竟隱藏着多大的祕密。
有些細心而專業的讀者可能已經發現了,我用本身的思路和措辭,粗略的解釋了有關 CSS 加載和渲染的知識,有些涉世未深的前端愛好者可能會一頭霧水,沒法做爲系統學習的依據。這不打緊,出來混,祖墳老是要刨的,想要透徹的學習相關內容,進一步瞭解底層原理的學者,我早已爲你備下了豐厚的見面禮~
有關link
和@import
在性能分析方面的比較,國外的高手早在多年前就曾執過筆:
愛好母語的請戳我:https://www.stevesouders.com/blog/2009/04/09/dont-use-import/
閱讀英語的請戳我:https://www.qianduan.net/high-performance-web-site-do-not-use-import/
有關瀏覽器內部工做原理的神做,也是幾年前出自歪果仁大牛:
1 爲普通話:https://kb.cnblogs.com/page/129756/
2 for English:http://taligarsiel.com/Projects/howbrowserswork1.htm