最近在做知識體系的覆盤,在覆盤的時候儘可能的查漏補缺。關於@import和link引入樣式的區別網上有很多種說法。大致有如下幾種,不過這其中會有我存疑的地方,我們可以一起來探討一下。
區別
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
引入的樣式。(???)
我們在網上搜尋關於這兩者的區別的時候通常會看見有第5條這麼一個說法。難道第5條真的是這樣嗎?有待商榷。
所以這裡我們就通過幾個demo來驗證一下第五條
再驗證之前我們先來說說css權重
的相關概念:
css的權重指的是選擇器的優先順序,CSS 選擇器的權重高,即選擇器的優先順序高。
css的優先順序表現在,對同一個html元素設定元素的時候,不同選擇器的優先順序不同,優先順序低的樣式將會被優先極高的樣式所覆蓋。
css的權重優先順序表現為:
!important > 行內樣式 > ID > 類、偽類、屬性 > 標籤名 > 繼承 > 萬用字元
為了便於理解權重的計算方式,我們按以下方式進行數值假設分析:
選擇器 | 權重 |
---|---|
萬用字元 | 0 |
標籤 | 1 |
類/偽類/屬性 | 10 |
ID | 100 |
行內樣式 | 1000 |
important | 無窮大 |
demo:
<!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>複製程式碼
根據上述計算得知:這個按鈕應該是黃色背景,白色字型。
這裡又回到我們的主題:link引入的樣式權重真的大於@import嗎?
難道引入css的方式也會有權重嗎?
上demo:
/* 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;
}複製程式碼
eg1)
<!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>複製程式碼
效果:
eg2)
<!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>複製程式碼
效果:
對比1和2兩個例子,我們發現link和@import這兩種引入css的方式並沒有權重方面概念,只是單純的展示出css的層疊行罷了。即寫在後邊都樣式會覆蓋前面的樣式。
eg3)
<!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>複製程式碼
效果:
eg4)
<!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>複製程式碼
效果:
分析例項3和例項4的結果可知:
對於例項3,我們看到紅色邊框,證明內聯樣式中使用@import引入的green.css已經生效,但其背景樣式被內聯樣式中的粉色背景層疊掉,這個現象表明,@import不只是如我們看到的那樣,處於內聯樣式頂部,其被引入的樣式,在結構上,也確實是被置於內聯樣式之前,所以內聯樣式才能夠層疊掉它。
同理,例項4中,在link標籤引入的blue.css檔案內,頂部同樣存在@import引入的green.css,紅色邊框依然可以證明,green.css已經生效,但其背景樣式被blue.css本身的藍色背景層疊掉,@import引入的樣式在blue.css中也是被置於它本身樣式之前的。
所以由上述例項證明link
引入的樣式權重大於@import
引入的樣式這麼說是不太合理的。
疑點?
我們上邊也說了關於link
和@import
的區別,在載入頁面的時候,不是說在link
引入的css樣式的時候會先於@import
載入嗎?那為啥link
引入的樣式又會覆蓋掉@import
引入的樣式啊?
首先我們來回顧一下關於瀏覽器執行過程的一些概念:
載入: 根據請求的url進行域名解析,然後向伺服器傳送請求,接收響應檔案(如HTML、CSS、JS、圖片等)。
解析: 對載入到的資源(HTML、CSS、JS等)進行語法解析,構建響應的內部資料結構(如HTML的DOM樹,JS物件的屬性表,css樣式規則等)。
渲染: 構建渲染樹,對各個元素進行位置計算、樣式計算等,然後根據渲染書完成頁面的佈局及繪製的過程(產生頁面的元素)。
所以根據我們上述的瀏覽器執行過程的理解以後,我們我繼續提出疑問:
link先於@import載入,是不是也先於@import渲染呢?
實際上,瀏覽器渲染的動作一般會執行多次的。最後一次渲染,一定是基於之前載入過的所有樣式整合後渲染樹進行繪製頁面的,已經被渲染過的頁面元素,也會被重新渲染。
那麼我們就可以把@import這種匯入 CSS 檔案的方式理解成一種替換,CSS 解析引擎在對一個 CSS 檔案進行解析時,如在檔案頂部遇到@import,將被替換為該@import匯入的 CSS 檔案中的全部樣式。
終於弄明白為何@import引入的樣式,會被層疊掉了。其雖然後被載入,卻會在載入完畢後置於樣式表頂部,最終渲染時自然會被下面的同名樣式層疊。