CSS學習摘要-層疊和繼承

来源:https://www.cnblogs.com/tielemao/archive/2018/06/01/9119755.html
-Advertisement-
Play Games

層疊 CSS 是 **Cascading Style Sheets** 的縮寫,這暗示層疊(cascade)的概念是很重要的。在最基本的層面上,它表明CSS規則的順序很重要,但它比那更複雜。什麼選擇器在層疊中勝出取決於三個因素(這些都是按重量級順序排列的——前面的的一種會否決後一種): 1. 重要... ...


當有多個選擇器作用在一個元素上時,哪個規則最終會應用到元素上?

其實這是通過層疊機制來控制的,這也和樣式繼承(元素從其父元素那裡獲得屬性值)有關。

元素的最終樣式可以在多個地方定義,它們以複雜的形式相互影響。這些複雜的相互作用使CSS變得非常強大,但也使其非常難於調試和理解。

層疊

CSS 是 Cascading Style Sheets 的縮寫,這暗示層疊(cascade)的概念是很重要的。在最基本的層面上,它表明CSS規則的順序很重要,但它比那更複雜。什麼選擇器在層疊中勝出取決於三個因素(這些都是按重量級順序排列的——前面的的一種會否決後一種):

  1. 重要性(Importance)
  2. 專用性(Specificity)
  3. 源代碼次序(Source order)

重要性

在CSS中,有一個特別的語法可以讓一條規則總是優先於其他規則:!important。(常見於應用於iconfont圖標屬性後面)把它加在屬性值的後面可以使這條聲明有無比強大的力量。

讓我們看一下這個例子:

<p class="better">This is a paragraph.</p>
<p class="better" id="winning">One selector to rule them all!</p>
#winning {
  background-color: red;
  border: 1px solid black;
}

.better {
  background-color: gray;
  border: none !important;
}

p {
  background-color: blue;
  color: white;
  padding: 5px;
}

這將生成以下:

讓我們一起來看看發生了什麼。

  1. 你可以看到第三條規則 colorpadding被運用了, 但 background-color沒有,為什麼?實際上,這三種情況都應該應用,因為在源順序後面的規則通常會覆蓋較早的規則。

  2. 然而, 在前面的規則被運用了,因為 IDs/class 選擇器優先於element選擇器。

  3. 這兩個元素都有 class並帶有 better屬性, 但是第二個元素有 id 值為winning 。 因為比起class而言id專用性更高(在一個頁面上id是唯一的, 但很多元素可以擁有相同的class — ID 選擇器在它們的目標中是非常優先的),紅色背景色和1pixel的黑色邊框都應應用於第二元素,第一個元素獲得灰色背景色,沒有邊框,如類所指定。

  4. 第二個元素獲得紅色背景色,但沒有邊框。為什麼?因為 !important 在第二條規則中的聲明——在 border: none之後寫入它意味著儘管id具有更高的優先性,該聲明也將優先於前面規則中的邊界值聲明。

註意: 重載這個 !important 聲明的唯一方法是在後面的源碼或者是一個擁有更高特殊性的源碼中包含相同的 !important 特性的聲明。

知道 !important存在是很有用的,這樣當你在別人的代碼中遇到它時,你就知道它是什麼了。但是!我們建議你千萬不要使用它,除非你絕對必須使用它。您可能不得不使用它的一種情況是,當您在CMS中工作時,您不能編輯核心的CSS模塊,並且您確實想要重寫一種不能以其他方式覆蓋的樣式。 但是,如果你能避免的話,不要使用它。由於 !important 改變了層疊正常工作的方式,因此調試CSS問題,尤其是在大型樣式表中,會變得非常困難。

要註意一個CSS聲明的重要性取決於它被指定在什麼樣式表內——用戶可以設置自定義樣式表覆蓋開發商的樣式,例如用戶可能有視力障礙,想設置字體大小對所有網頁的訪問是雙倍的正常大小,以便更容易閱讀。

相互衝突的聲明將按以下順序適用,後一種將覆蓋先前的聲明

  1. 在用戶代理樣式表的聲明 (例如:瀏覽器在沒有其他聲明的預設樣式).
  2. 用戶樣式表中的普通聲明(由用戶設置的自定義樣式)。
  3. 作者樣式表中的普通聲明(這是我們設置的樣式,Web開發人員)。
  4. 作者樣式表中的重要聲明
  5. 用戶樣式表中的重要聲明

Web開發者的樣式表覆蓋用戶的樣式表是合理的,所以設計可以保持預期,但是有時候用戶有很好的理由來重寫web開發人員樣式,如上所述,這可以通過在用戶的規則中使用!important

專用性

專用性基本上是衡量選擇器的具體程度的一種方法——它能匹配多少元素。如上面所示的示例所示,元素選擇器具有很低的專用性。類選擇器具有更高的專用性,所以將戰勝元素選擇器。ID選擇器有甚至更高的專用性, 所以將戰勝類選擇器. 戰勝ID選擇器的唯一方法是使用 !important

一個選擇器具有的專用性的量是用四種不同的值(或組件)來衡量的,它們可以被認為是千位,百位,十位和個位——在四個列中的四個簡單數字:

  1. 千位:如果聲明是在style 屬性中該列加1分(這樣的聲明沒有選擇器,所以它們的專用性總是1000。)否則為0。
  2. 百位:在整個選擇器中每包含一個ID選擇器就在該列中加1分。
  3. 十位:在整個選擇器中每包含一個類選擇器、屬性選擇器、或者偽類就在該列中加1分。
  4. 個位:在整個選擇器中每包含一個元素選擇器或偽元素就在該列中加1分。

註意: 通用選擇器 (*), 複合選擇器 (+, >, ~, ' ') 和否定偽類 (:not) 在專用性中無影響。

下表顯示了幾個示例。試著通過這些,並確保你理解他們為什麼具有我們給予他們的專用性。

選擇器 千位 百位 十位 個位 合計值
h1 0 0 0 1 0001
#important 0 1 0 0 0100
h1 + p::first-letter 0 0 0 3 0003
li > a[href*="zh-CN"] > .inline-warning 0 0 2 2 0022
#important div > div > a:hover, 在一個元素的 <style>屬性里 1 1 1 3 1113

在我們繼續之前,讓我們看看一個行動中的例子。
這是我們將要使用的HTML:

<div id="outer" class="container">
  <div id="inner" class="container">
    <ul>
      <li class="nav"><a href="#">One</a></li>
      <li class="nav"><a href="#">Two</a></li>
    </ul>
  </div>
</div>

下麵是CSS的示例:

/* specificity: 0101 */
#outer a {
  background-color: red;
}

/* specificity: 0201 */
#outer #inner a {
  background-color: blue;
}

/* specificity: 0104 */
#outer div ul li a {
  color: yellow;
}

/* specificity: 0113 */
#outer div ul .nav a {
  color: white;
}

/* specificity: 0024 */
div div li:nth-child(2) a:hover {
  border: 10px solid black;
}

/* specificity: 0023 */
div li:nth-child(2) a:hover {
  border: 10px dashed black;
}

/* specificity: 0033 */
div div .nav:nth-child(2) a:hover {
  border: 10px double black;
}

a {
  display: inline-block;
  line-height: 40px;
  font-size: 20px;
  text-decoration: none;
  text-align: center;
  width: 200px;
  margin-bottom: 10px;
}

ul {
  padding: 0;
}

li {
  list-style-type: none;
}

我們從這個代碼中得到的結果如下:

這裡發生了什麼?首先,我們只對本例的前七個規則感興趣,正如您將註意到的,我們已經在每個註釋中包含了它們的專用性值。

  • 前兩個選擇器正在競爭鏈接的背景顏色的樣式——第二個贏得並使背景色為藍色,因為它有一個額外的ID選擇器在鏈中:其專用性值為201比101。
  • 第三個和第四個選擇器在鏈接文本顏色的樣式上進行競爭——第二個選擇器獲勝,使文本變白,因為缺少一個元素選擇器,缺少的選擇器被換成類選擇器,它的值是十,而不是個位。所以專用性值為113和104。
  • 選擇器5 - 7在徘徊在鏈接附近時的樣式進行競爭。選擇器六明顯地輸給了了五,其專用性值為23和24——它在鏈中少了一個元素選擇器。然而選擇器七同時擊敗了五和六——它有與五相同數量的子選擇器在鏈中,但一個元素已被換為了一個類選擇器。所以獲勝的專用性值是33比23和24。

源代碼次序

如上所述,如果多個相互競爭的選擇器具有相同的重要性和專用性,那麼第三個因素將幫助決定哪一個規則獲勝——後面的規則將戰勝先前的規則。例如:

p {
  color: blue;
}

/* This rule will win over the first one */
p {
  color: red;
}

而在這個例子中的第一個規則將獲勝,因為專用性高於源代碼順序:

/* This rule will win */
.footnote {
  color: blue;
}

p {
  color: red;
}

關於規則混合的一點註記

在考慮所有這些層疊理論和什麼樣式優先於其他樣式被應用時,你應該記住的一件事是,所有這些都發生在屬性級別上——屬性覆蓋其他屬性,但你不會讓整個規則凌駕於其他規則之上。
當多個CSS規則匹配相同的元素時,它們都被應用到該元素中。只有在這之後,任何相互衝突的屬性才會被評估,以確定哪種風格會戰勝其他類型。

簡記:只有相同的屬性應用發生衝突後才會產生覆蓋

讓我們看一個例子。首先,一些HTML:

<p>I'm <strong>important</strong></p>

現在一些CSS風格與它:

/* specificity: 0002 */
p strong {
  background-color: khaki;
  color: green;
}

/* specificity: 0001 */
strong {
  text-decoration: underline;
  color: red;
}

Result:

在這個例子中,因為專用性的關係,第一條規則中的color屬性覆蓋掉了第二條中的顏色值。但是,對於第一條中的 background-color和第二條中的text-decoration 的屬性都在strong元素之中得到了體現。你也註意到了這個元素之中的字體是加粗的:這是瀏覽器預設的樣式規則。

繼承

CSS繼承是我們需要研究的最後一部分,以獲取所有信息並瞭解什麼樣式應用於元素。

其思想是,應用於某個元素的一些屬性值將由該元素的子元素繼承,而有些則不會。

  • 例如,對 font-familycolor進行繼承是有意義的,因為這使得您可以很容易地設置一個站點範圍的基本字體,方法是應用一個字體到 <html> 元素;然後,您可以在需要的地方覆蓋單個元素的字體。如果要在每個元素上分別設置基本字體,那就太麻煩了。

  • 再如,讓 margin paddingborderbackground-image 不被繼承是有意義的。想象一下,如果您將這些屬性設置在一個容器元素上,並將它們繼承到每個子元素,然後不得不將它們全部放在每個單獨的元素上,那麼將會出現的樣式/佈局混亂。

哪些屬性預設被繼承哪些不被繼承大部分符合常識。如果你想確定,你可以參考CSS參考資料—— 每個單獨的屬性頁都會從一個彙總表開始,其中包含有關該元素的各種詳細信息,包括是否被繼承。

註:
font-family允許您通過給定一個有先後順序的,由字體名或者字體族名組成的列表來為選定的元素設置字體。 屬性的值用逗號隔開。瀏覽器會選擇列表中第一個該電腦上有安裝的字體,或者是通過 ‘ @font-face 指定的可以直接下載的字體。

padding屬性設置一個元素的內邊距,padding 區域指一個元素的內容和其邊界之間的空間,該屬性不能為負值。

background-image 屬性用於為一個元素設置一個或者多個背景圖像。圖像在繪製時,以z方向堆疊的方式進行。先指定的圖像會在之後指定的圖像上面繪製。因此指定的第一個圖像最接近用戶。

控制繼承

CSS為處理繼承提供了四種特殊的通用屬性值:

  • inherit: 該值將應用到選定元素的屬性值設置為與其父元素一樣。
  • initial :該值將應用到選定元素的屬性值設置為與瀏覽器預設樣式表中該元素設置的值一樣。如果瀏覽器預設樣式表中沒有設置值,並且該屬性是自然繼承的,那麼該屬性值就被設置為 inherit
  • unset:該值將屬性重置為其自然值,即如果屬性是自然繼承的,那麼它就表現得像 inherit,否則就是表現得像 initial
  • revert:如果當前的節點沒有應用任何樣式,則將該屬性恢復到它所擁有的值。換句話說,屬性值被設置成自定義樣式所定義的屬性(如果被設置), 否則屬性值被設置成用戶代理的預設樣式。

註意: initialunset 不被IE支持。

initial 是將屬性的初始值( initial value)賦給元素 . initial 適用於所有的css 屬性(屬性的initial值可在屬性表中查到),包括css 簡寫屬性(全局屬性)all.

inherit 值是最有趣的——它允許我們顯式地讓一個元素從其父類繼承一個屬性值。

讓我們看一個例子。首先有以下一段HTML:

<ul>
  <li>Default <a href="#">link</a> color</li>
  <li class="inherit">Inherit the <a href="#">link</a> color</li>
  <li class="initial">Reset the <a href="#">link</a> color</li>
  <li class="unset">Unset the <a href="#">link</a> color</li>
</ul>

現在用CSS給它添加樣式:

body {
  color: green;
}

.inherit a {
  color: inherit;
}

.initial a {
  color: initial
}

.unset a {
  color: unset;
}

Result:

讓我們解釋這裡發生了什麼:

  • 我們首先設置<body>color為綠色。
  • 由於color屬性是自然繼承的,所有的body子元素都會有相同的綠色。需要註意的是預設情況下瀏覽器設置鏈接的顏色為藍色,而不是自然繼承color屬性,因此在我們列表中的第一個鏈接是藍色的。
  • 第二個規則設置一個類 inherit 的元素內的鏈接,並從父類繼承它的顏色。在這種情況下, 意思是說鏈接繼承了父元素<li> 的顏色,預設情況下<li>的顏色來自於它的父元素 <ul> , 最後<ul>繼承自 <body>元素,而<body>color 根據第一條規則設置成了綠色。
  • 第三個規則選擇了在元素上使用類 initial 的任意鏈接然後設置他們的顏色為 initial 。通常, initial 的值被瀏覽器設置成了黑色,因此該鏈接被設置成了黑色。
  • 最後一個規則選擇了在元素上使用類 unset 的所有鏈接然後設置它們的顏色為 unset ——即我們不設置值。因為color屬性是一個自然繼承的屬性,它實際上就像把值設置成 inherit 一樣。結果是,該鏈接被設置成了與body一樣的顏色——綠色。

重新設置所有的屬性值

CSS速寫屬性 all 能夠被應用到每一個繼承屬性,一次性應用所有的繼承屬性。這裡的值可以是繼承屬性里的任何一個 (inherit, initial, unset, or revert)。對於撤銷對樣式的修改,這是非常方便的一種方式。然後你就可以在開始新的修改之前,返回到一個已知的開始點。

全文摘要自MDN網路開發者網站
end
2018-5-31 周四


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...