摘要:結論就結論而言,強烈建議使用標簽,慎用方式。這樣可以避免考慮的語法規則和注意事項,避免產生資源文件下載順序混亂和請求過多的煩惱。區別從屬關系區別是提供的語法規則,只有導入樣式表的作用是提供的標簽,不僅可以加載文件,還可以定義連接屬性等。
我們都知道,外部引入 CSS 有2種方式,link標簽和@import。
它們有何本質區別,有何使用建議,在考察外部引入 CSS 這部分內容時,經常被提起。
如今,很多學者本著知其然不欲知其所以然的學習態度,不求甚解,只求結論。
所以,本文遵循 css hack 的漸進識別原則,
結論 → 區別 → 爭議 → 細節 → 祖墳 → 感想,逐漸加深理論層級,
力爭每個 level 的讀者,都能 get 到自己想要的內容,不必繼續閱讀下去。
就結論而言,強烈建議使用link標簽,慎用@import方式。
這樣可以避免考慮@import的語法規則和注意事項,避免產生資源文件下載順序混亂和http請求過多的煩惱。
1.從屬關系區別
@import是 CSS 提供的語法規則,只有導入樣式表的作用;link是HTML提供的標簽,不僅可以加載 CSS 文件,還可以定義 RSS、rel 連接屬性等。
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(無窮大) |
再舉實例:
Document
每個樣式的權重值,都在實例中,以注釋的形式標明。
根據權重值可知,最終,這個按鈕的樣式一定是,藍色背景,白色字,結果如下圖:
存在!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:
Document
實例1結果如下圖:
實例2:
Document
實例2結果如下圖:
對比實例1和實例2這兩個正好相反的結果可知,link和@import并沒有產生類似權重的效果,只是單純的體現了CSS的層疊性,寫在后面的樣式,覆蓋前面的樣式。
實例3:
Document
實例3結果如下圖:
實例4:
Document
實例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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/96789.html
摘要:結論就結論而言,強烈建議使用標簽,慎用方式。這樣可以避免考慮的語法規則和注意事項,避免產生資源文件下載順序混亂和請求過多的煩惱。區別從屬關系區別是提供的語法規則,只有導入樣式表的作用是提供的標簽,不僅可以加載文件,還可以定義連接屬性等。 我們都知道,外部引入 CSS 有2種方式,link標簽和@import。它們有何本質區別,有何使用建議,在考察外部引入 CSS 這部分內容時,經常被提...
摘要:一概念通常的程序的構架是指將一個程序分割為源代碼文件的集合以及將這些部分連接在一起的方法。的程序構架可表示為一個程序就是一個模塊的系統。它有一個頂層文件啟動后可運行程序以及多個模塊文件用來導入工具庫。導入是中程序結構的重點所在。 一、概念 通常的Python程序的構架是指:將一個程序分割為源代碼文件的集合以及將這些部分連接在一起的方法。 Python的程序構架可表示為: showImg...
摘要:獲取資源失敗,將該線程加入等待隊列尾部,標記為獨占模式。如果有剩余資源則會喚醒下一個線程,且整個過程忽略中斷的影響。 AQS概念及定義 ASQ:AbstractQueuedSynchronizer 它維護了一個volatile int state(代表共享資源)和一個FIFO線程等待隊列(多線程爭用資源被阻塞時會進入此隊列,有個內部類Node定義了節點。隊列由AQS的volatile成...
閱讀 2949·2021-11-23 09:51
閱讀 1666·2021-10-15 09:39
閱讀 1056·2021-08-03 14:03
閱讀 2880·2019-08-30 15:53
閱讀 3437·2019-08-30 15:52
閱讀 2487·2019-08-29 16:17
閱讀 2787·2019-08-29 16:12
閱讀 1647·2019-08-29 15:26