【Hello CSS】第七章-CSS的繼承與可變性

陳大魚頭發表於2019-05-03

繼承

繼承(英語:inheritance)物件導向軟體技術當中的一個概念。在 CSS 中與 層疊(英語:Cascade) 一起描述瞭如何設定樣式規則,併為所有元素的所有屬性賦值。這兩個屬性同屬規範 “ CSS Cascading and Inheritance Level ”。CSS中的 繼承 實際上是父級元素對子元素的影響。

在之前的文章中,我們介紹過 層疊(優先順序) 的規則,這裡我們先複習一下:

選擇器 千位 百位 十位 個位 合計值
h1 0 0 0 1 0001
#indentifier 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
沒有選擇器, 規則在一個元素的 <style> 屬性裡 1 0 0 0 1000

魚頭注:有很多人會認為 !important 也參與了優先順序的排列,但 !important 是在優先順序的規則之外的,如果參與了優先順序的排列,意思就是 !important 是可以被覆蓋的,但事實顯然不是。

接下來我們談談 CSS中的繼承

特殊的通用屬性值

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

意義
inherit 屬性初始值。
initial 繼承的值。
unset 如果使用 unset 的屬性為繼承屬性,則將其視為 inerit,否則則視為 initial
revert 屬性值被設定成自定義樣式所定義的屬性(如果被設定), 否則屬性值被設定成使用者代理的預設樣式。

reset屬性值

在這裡分享一個CSS屬性all。CSS all 簡寫屬性 將除卻 unicode-bididirection 之外的所有屬性重設至其初始值,或繼承值。 all 的值可以如下:

/* Global values */
all: initial
all: inherit
all: unset

/* CSS Cascading and Inheritance Level 4 */
all: revert;
複製程式碼

以上四值的功能如上面的表一樣。這裡我們重點分享一下 revertrevert關鍵字指定依賴於CSS宣告的源:

  • 使用者代理源(user-agent origin):瀏覽器會有一個 基本的樣式表 來給任何網頁設定預設樣式,這些樣式統稱使用者代理樣式,等同於 unset
  • 使用者源(user origin):網站的使用者(或讀者)所選擇的自定義樣式,主要是根據使用者的一員定製(例如使用者自定義的系統主題與字型)。
  • 作者源(author origin):網站開發者定義的樣式。

例子如下:

<style>
    body {
        color: #404040;
        background: #DDDDDD;
    }
    blockquote {
        border-radius: 5px;
        padding: 15px;
        background: #0F60B6;
        color: #FFFFFF;
        display: table;
    }
    .all-unset {
        all: unset;
    }
    .all-initial {
        all: initial;
    }
    .all-inherit {
        all: inherit;
    }
</style>
<h1 aria-level="1">雞湯大全</h1>
<section aria-level="2">
    <h2 role="heading">名言警句</h2>
    <blockquote cite="https://www.juzimi.com/album/3903593">
        人若志趣不遠,心不在焉,雖學不成。
        <cite>— 張載</cite>
    </blockquote>
</section>
<section aria-level="2">
    <h2 role="heading">名言警句(all: unset)</h2>
    <blockquote class="all-unset" cite="https://www.juzimi.com/album/3903593">
        人若志趣不遠,心不在焉,雖學不成。
        <cite>— 張載</cite>
    </blockquote>
</section>
<section aria-level="2">
    <h2 role="heading">名言警句(all: initial)</h2>
    <blockquote class="all-initial" cite="https://www.juzimi.com/album/3903593">
        人若志趣不遠,心不在焉,雖學不成。
        <cite>— 張載</cite>
    </blockquote>
</section>
<section aria-level="2">
    <h2 role="heading">名言警句(all: inherit)</h2>
    <blockquote class="all-inherit" cite="https://www.juzimi.com/album/3903593">
        人若志趣不遠,心不在焉,雖學不成。
        <cite>— 張載</cite>
    </blockquote>
</section>
複製程式碼

效果如下:

【Hello CSS】第七章-CSS的繼承與可變性

程式碼在我codepen (codepen.io/krischan77/…) 中,大家可以隨時檢視。

魚頭注:至於CSS中可繼承的屬性有點多,我就不列出來了,各位有興趣的可以看看這個問題:stackoverflow.com/questions/5…

計算值(Computed Value)

計算值(Computed Value) 是解析指定屬性值的結果,通過將其絕對化用以繼承。

計算值(Computed Value) 用以繼承時是由父節點傳達到子節點的值,由於歷史原因,它不一定是由 getComputedStyle() 返回的結果。

常見的計算值(Computed Value) 有:emexvhvwsmallerbolder等不固定具體px尺寸的值。

下面是一個不同計算值單位下盒子的寬度變化的DEMO

程式碼有點長,就不貼出來了,有興趣可以點開連結嘗試一下:krissarea.gitee.io/blog/css/un…

【Hello CSS】第七章-CSS的繼承與可變性

功能表示法(Functional Notations)

功能表示法是一種元件值,可以表示更復雜的型別或呼叫特殊處理。主要分有以下三個部分:

  • 數學表示式(用以四則運算):calc()min()max()clamp()
  • 切換值(允許子元素迴圈呼叫傳入引數):toggle()
  • 屬性引用(獲取引用的屬性):attr()

以上功能屬性,在之前的章節中也提到過,目前能用的就只有 calc()attr(),但是即便如此,這兩個函式已經卻也已經發揮出了很強大的功能。

var()

var()CSS Custom Properties for Cascading Variables Module Level 1 的內容,中文名叫 自定義屬性並不叫CSS變數並不叫CSS變數並不叫CSS變數,重要的內容說三次。

語法如下:

var( <custom-property-name> , <declaration-value>? )
複製程式碼

方法的第一個引數是要替換的自定義屬性的名稱。函式的可選第二個引數用作回退值。如果第一個引數引用的自定義屬性無效,則該函式將使用第二個值。

我們可以在任何選擇器中宣告,例子如下:

// 下面的定義都是有效的
:root {
    --color: red;
}
@media (min-width: 300px) {
    :root {
        --color: blue;
    }
}
.color {
    --color: white;
}
a {
    color: var(--color, black);
}
複製程式碼

從上面的程式碼我們可以知道,自定義屬性不僅僅可以在全域性作用域下定義,甚至也可以在區域性作用域下定義,這點是一些 CSS處理器 所無法實現的。

我們知道,CSS目前還沒有條件判斷的功能,但是我們藉由數學表示式函式 calc() 也可以實現很多有趣的功能。

這裡我們分享一個由 var()calc() 實現的進度條功能,效果如下:

<style>
    * {
        margin: 0;
        padding: 0;
    }
    .progress {
        height: 20px;
        width: 300px;
        background-color: #f5f5f5;
    }
    .progress::before {
        counter-reset: progress var(--percent, 0);
        content: counter(progress) '%\2002';
        display: block;
        height: 20px;
        line-height: 20px;
        width: calc(300px * var(--percent, 0) / 100);
        font-size: 12px;
        color: #fff;
        background-color: #2486ff;
        text-align: right;
        white-space: nowrap;
        overflow: hidden;
    }
</style>
<div id="progress" class="progress"></div>
<script>
    'use strict';
    let count = 0;
    const progressAdd = count => {
        if (count < 100) {
            count++;
            progress.style = `--percent: ${count}`;
            setTimeout(() => {
                progressAdd(count);
            }, 100);
        };
    };
    progressAdd(count);
</script>
複製程式碼
【Hello CSS】第七章-CSS的繼承與可變性

程式碼在我codepen: https://codepen.io/krischan77/pen/QPezjB中,各位隨時可以去看效果。

currentColor

關鍵字 currentColor 是屬性 color 的值,如果 color 上設定 currentColor ,則將其視為 color: inherit

borderbox-shadow 預設的顏色就是當前的文字顏色,也就是類似 currentColor

嗯,所以有什麼用?

我們可以通過 currentColor 來輕鬆實現換膚功能。DEMO如下:

【Hello CSS】第七章-CSS的繼承與可變性
<style>
    html,
    body {
      color: #000000;
    }
    .box {
      width: 100px;
      height: 100px;
      background: currentColor;
      padding: 10px;
    }
</style>
<div id="box" class="box"></div>
  你想換的顏色:<input id="color" name="color" type="color" value="#000000" autocomplete="off">
<script>
    'use strict';
    color.onchange = event => {
        document.querySelector('body').style.color = color.value;
    };
</script>
複製程式碼

currentColorCSS3 中非常好用的一個關鍵字,利用它我們就可以輕鬆實現文字顏色與圖形之間的互動。

說到這裡,不知道大家有沒有覺得很奇怪, 像 multi-word 這種具有連字元的單詞才是 CSS 中的常規命名,而 currentColor 確是駝峰命名?如果你知道答案的話,可以在下方留言區域留言回答,不知道的話也沒關係,可以持續關注魚頭的 『Hello CSS』,魚頭會在下一篇文章中解答。

後記

本文主要簡單分享了 CSS 的繼承與可變性,同時也再次地回顧了之前系列中所分享過的層級,函式等內容,一方面是想做個整理歸納,如果 CSS 屬性分配得恰當,不僅可以減輕我們很多的工作量,也可以輕鬆實現一些比較有趣的效果,更重要是可以減少JSCSS 的耦合度,對我們的開發與後期維護也是有很大幫助的。

大家也不妨多挖掘挖掘 CSS 的潛在能力,這也許會帶來意想不到的收穫。

參考資料:

CSS Cascading and Inheritance Level 4

CSS Values and Units Module Level 4

Origin of CSS declarations

【Hello CSS】系列

【Hello CSS】是以CSS基礎概念為主題的系列文章,旨在幫助大家更深刻地瞭解並且提高CSS在各位開發者心目中的地位。由於魚頭我水平有限,文筆有限,如果各位在文章中發現有任何不合理,不正確的地方,還煩不吝指出,我會非常感謝的;如果通過文章有任何想法或疑問,也希望各位能積極留言,我們互相探討;如果通過本系列文章有所收穫,這就讓魚頭我喜不自勝了!



如果你也喜歡`CSS`,喜歡探討技術,或者對本文,本系列有任何的意見或建議,魚頭非常希望你能加入一個有趣的微信群 — “進擊的CSS”。你可以掃描下方二維碼,新增魚頭微信,新增時註明 “加群”,如果你覺得我的文章有趣,歡迎關注微信公眾號“魚頭的Web海洋”。衷心希望可以遇見你。

【Hello CSS】第七章-CSS的繼承與可變性

下一篇

第八章-影像中的CSS

歷史文章傳送門

  1. 序章-起源

  2. 第一章-CSS的語法與工作流

  3. 第二章-CSS的邏輯屬性與盒子模型

  4. 第三章-瀏覽器的檢視與座標

  5. 第四章-HTML的標籤與語意

  6. 第五章-CSS的選擇器與函式

  7. 第六章-文件流與排版

  8. 第七章-CSS的繼承與可變性

相關文章