久久一区二区三区超碰国产精品,亚洲人成在线网站,国产在线精品一区免费香蕉,国产精品免费电影

歡迎您訪問頭號作家解讀 UI 框架樣式修改:顏色主題配置與自定義變量!

頭號作家解讀 UI 框架樣式修改:顏色主題配置與自定義變量

更新時間:2024-05-29 21:17:53作者:佚名

專欄介紹

“頂級寫手”是OPPO工程師解讀最新熱點技術的專欄,在這里你不僅可以看到最新最熱的動態,還能和OPPO優秀的工程師一起學習技術知識。

頂級作家

■鮑勃

■一位在前端領域耕耘9年多的前端“新生代IT民工”,立志分享各種前端酷知識。

01

背景

相信用過 UI 框架的同學應該或多或少都修改過它的樣式,最常見需要修改的樣式應該就是:顏色。大多數情況下,官方框架可能會提供主題配置,比如主題顏色配置(使用 Sass 變量)或者 Ant 主題顏色配置(使用 Less 變量)。你可以定義 @-color(Ant) 或者 $--color-() 這樣的變量來定制想要的主題顏色,比如 OPPO 綠色。

但相信大家都經歷過這種情況,因為是借助了 CSS 預處理器的能力,而非原生的 CSS 支持,這不僅意味著需要打包工具的支持,也意味著這些變量并不是真正的“變量”。它們在打包時會被替換成 CSS 能夠識別的顏色值,無法再通過改變其中一種 - 來改變頁面上所有相關的顏色。對于只使用一套 OPPO 綠色的場景來說這還好,但如果要改變動態主題色怎么辦?或者像夜間模式這種需要改變顏色的場景怎么辦?這對于 CSS 來說其實并不容易。

使用 CSS 不是不可以,只是開發體驗不好。比如可以為不同的主題設置不同的 class,并根據這些不同的 class 將所有使用顏色的地方重寫。試想一下,業務 CSS 中有 20 個地方用到了主題顏色custom什么意思,每增加一套主題,就需要重寫這 20 個地方的顏色定義。這其實也是我們之前常用的方法。

當然,也有辦法將瀏覽器版的CSS預處理器嵌入到頁面中,如果你已經在網上使用過這種方法,或者有這樣的想法,請務必看完本文,思考是否還有其他方法。

遇到需要動態更換主題的同學肯定都搜索過并了解過CSS自定義變量的概念,如果你還沒有用過,不用擔心,看完你就懂了。

不知道大家有沒有注意到,標題里有一個奇怪的---,和變量定義方式$--color-很像。那么這是什么呢?CSS自定義變量就是這么定義的。

02

基本定義

我們先來看一下基本的定義。CSS自定義變量由兩部分組成 - 加一個名稱。名稱和變量名規則差不多,比如區分大小寫(這個和普通的CSS屬性名不同,CSS屬性名一般不區分大小寫),但不同之處在于CSS自定義變量名可以以數字開頭,包括純數字,例如-1就是合法的CSS自定義變量,甚至允許使用漢字,甚至允許使用表情符號。

custom什么意思_意思相近的兩字詞_意思相近的字組成詞語

正如那句老話所說:你能做某件事并不意味著你應該做它。想想當你看到有人在別人的代碼中寫了 --1: 5px, --2: red,然后毫無理由地到處使用 --1 和 --2 時,試著表達你的感受。

其實 CSS 規范和 MDN 文檔中都使用了“自定義屬性”這個術語,但是“自定義屬性”看起來不如“自定義變量”那么清晰吸引人,所以本文使用了“自定義變量”這個術語。請記住它對應的是“自定義屬性”或者規范中提到的與變量相關的術語:“自定義變量”。

這里之所以可以是數字開頭,也可以是純數字,準確的說是因為前面有一個--,這個--不能算是一個變量名,因為實際的名字應該包含整個--。

但是,有了名字并不代表變量就可以用,需要賦值才有用。而且,CSS自定義變量必須存在于CSS的一定的元素規則定義中,不能像全局變量那樣寫在最外層。當然,全局變量也有相應的定義方式,后面會提到。所以CSS自定義變量的完整定義應該是:

:root {  --custom-variable: ;}
/* 舉幾個栗子 */html { --color-primary: green; --color-disabled: gray; --wide-border: 3px;}

除了在CSS文件、樣式屬性、對應方法中定義外,請注意,這也是在“某一元素規則的定義”中,因為它只對該屬性所在的元素及其子元素有效。

03

使用自定義變量

用法

好的,現在我們有了一個有效的 CSS 自定義變量,如何使用它?CSS 定義了 var() 方法,例如,您可以使用 var(--color-) 來讀取它。因此,可以像這樣設置具有淺綠色背景的 div 的樣式:

div {  background-color: var(--color-primary);}

var() 方法也支持默認值,當對應變量 或者 value 為 時,會讀取默認值。定義很簡單,用 隔開,后面的值就是默認值。例如 var(--color-,blue),當 --color- 或者 value 等于 時,會返回 blue。

但請注意,如果有多個逗號,則第一個逗號后面的整個值將作為默認值,而不是用逗號分隔。所以 var(--color-,blue,cyan) 的默認值是 blue, cyan。

在定義自定義變量的時候,還可以使用其他自定義變量。同時,var() 支持多層嵌套,因此默認值也可以是另一個自定義變量。例如以下形式:

div.bordered {  --color-border: var(--color-secondary, green);  /* 注意 --color-secondary 并未定義 */  border: var(--wide-border) var(--color-border) solid;  color: var(--color-text, var(--color-disabled, black));}

看到這里,大家應該知道怎么用了,但是為什么說了這么久,好像跟 CSS 預處理器的變量定義沒什么區別。好啦,別著急,我先問大家,還記得 CSS 縮寫里的 C 代表什么嗎?沒錯,就是“”:“”。這個詞也是 CSS 的獨特魅力所在,也是最容易讓人混淆的部分。不過,相信看文章的大家應該對 的優先級很熟悉了,如果不熟悉的話趕緊復習一下吧。為什么突然提到它呢?因為 CSS 自定義變量也遵循了 的概念。相同的變量定義會默認繼承,優先級高的定義會覆蓋優先級低的定義。這也是變量能“動態”改變其值的重要原因。

那么思考一下,如果前面所有的代碼塊都是在同一個頁面中依次定義,而頁面中有一個div和一個div,那么它們應該分別如何顯示呢?

意思相近的兩字詞_意思相近的字組成詞語_custom什么意思

了解了用法之后,假設你需要為這個頁面添加多個主題樣式,結合上面提到的級聯,你想到怎么添加了嗎?沒錯,我們可以用新樣式覆蓋變量:

.pink-theme {    --color-primary: pink;    --color-border: deeppink;}.gold-theme {    --color-primary: gold;    --color-border: goldenrod;}/* 還可以加更多 */

當然如果你不想添加class的話,也可以直接將樣式寫在對應的標簽上來覆蓋。

正如文章開頭所說,這種動態改變 CSS 中變量的值的功能在 CSS 預處理器中是無法輕易做到的,因為它們的變量定義就像它們的名字一樣,都是經過預先處理并放置在 CSS 中的。這也是 CSS 自定義變量相較于預處理器的一大優勢。

全局變量

看完前面的使用部分,大家有沒有搞清楚如何定義一個全局的 CSS 變量呢?因為自定義變量默認是被繼承的,所以簡單來說就是把樣式放到覆蓋范圍最廣的根元素上,也就是 HTML 中的元素上(其實一般情況下放在那里應該就可以了)。

上例中寫了一個 :root 偽類,這個偽類也引用了根元素,在 HTML 中也引用了 html 元素,這有什么區別呢?比如下面的定義中,div 的背景應該是什么顏色呢?

:root {  --color-bg: red;}html {  --color-bg: blue;}div {  background-color: var(--color-bg);}

如果你看實際的頁面,會發現是紅色的。為什么呢?:root 是偽類,所以是類的優先級。回想一下優先級的定義,類的優先級要高于元素類型選擇器的 html。

除了這種通過繼承來增加覆蓋率的形式之外,還有一種定義全局變量的方式,后面會提到。首先我們來看幾個問題。

無效值

從上面的用法來看,一般情況下,CSS 自定義變量可以簡單理解為在調用 var() 的地方將其值替換為文本,但在實現上還是有些區別的。拋開 CSS 解析計算過程的細節不談,可以看作是 CSS 解析器忽略了使用自定義變量的屬性值的語法檢查,即不管該值本身是否可以在對應屬性中使用。所以即使給自定義變量傳遞了非法值,這個屬性還是會被正常解析,只是在計算值的時候會出錯;這不同于直接寫入非法值,CSS 解析器會提前檢測到語法錯誤并忽略這條規則。

這樣可能有點讓人困惑,我們以MDN上的例子為例,做一個簡單的擴展:

:root { --text-color: 16px; }p { color: blue; }p { color: var(--text-color); }
div { color: blue; }div { color: 16px; }

如果你打開 demo 頁面,會發現第一行〈p〉是黑色的,而第二行〈div〉是藍色的。這是因為在使用 CSS 自定義變量的〈p〉定義中,color:var(--text-color)被正常解析,覆蓋了之前定義的color:blue(CSS 解析器一般會直接丟棄這個沒用的規則定義)。然后在替換-text-color 的時候發現它不是一個值,不是合法的顏色,導致〈p〉元素的顏色定義被非法重置。因為color是繼承的屬性,所以〈p〉會首先嘗試取繼承的值。由于 demo 中上沒有定義color,所以使用了繼承的瀏覽器默認樣式color:black。這里因為color:16px在解析過程中被瀏覽器認為是非法的而被忽略,所以選擇了之前有效的定義color:blue。

custom什么意思_意思相近的兩字詞_意思相近的字組成詞語

無效值重置和 CSS 全局關鍵字中 unset 的效果一致custom什么意思,即對繼承的屬性啟用 unset 時相當于繼承父級,對繼承的屬性禁用 unset 時相當于初始值。這三個字也是 CSS 的三個全局關鍵字。另外請注意,這三個關鍵字在使用自定義變量時也是有效的,將自定義變量值設置給它們時,就意味著對這個自定義變量執行 unset,以及操作:

:root {  --text-color: green;  color: red;}div {  --text-color: inherit;  color: var(--text-color);}

在上面的例子中,div的文字顏色會是綠色而不是紅色,因為這意味著自定義變量是從父級繼承下來的,也就是--text-color的值被計算為綠色,而不是用color:;替換后續color屬性的文字。

另一個具有此功能的關鍵字可能是臭名昭著的 !。當用于自定義變量時,它還意味著自定義變量本身具有 ! 的優先級,而不是將其替換為文本。我不會為此寫一個例子,我留給你自己去嘗試。

因為不是文本替換,所以有些地方不能寫自定義變量。比如不能寫自定義變量來替換 CSS 屬性名,也不能把值中的數字和單位分開留學之路,用自定義變量替換:

:root {  --property-name: padding;  --padding:10;}
p { var(--property-name):100px;/* 語法錯誤,忽略 */}p { padding:10px; padding:var(--padding)px; /* 正常解析但計算值失敗,等同于 padding: unset,所以前一條規則會被覆蓋 */}p.correct { padding: calc(var(--padding)*1px); /* 注意可以利用 calc() 來實現單位 */}

注意上面 p 的第二個定義 :10px; 是無效的,因為 var(--)px 在語法上不算無效,但實際計算時發現無法正確計算值,所以相當于 unset 了。不過如果你確實想只定義一個數字,并且在使用時加上單位,也可以使用例子中的 calc() 方法來實現。

雖然您不能像本例一樣連接單元,但是您可以使用 CSS 自定義變量將屬性值拆分為多個部分值,這將在后面的示例中提到。

循環引用

CSS 自定義變量允許你在 var() 內部嵌入另一個 var(),但不可避免地存在一個問題:

:root {  --margin:10px;}div {  --padding: calc(var(--margin)-10px);  margin:var(--margin);  padding:var(--padding);}div.cyclic {   --margin: calc(var(--padding)+10px);}

那么,div.的--和--該怎么解析呢?規范中定義,如果在同一個元素下發生循環引用,則本次循環內的所有自定義變量都等于該值,也就是值。

注意關鍵字“同一元素”,因為自定義變量默認是繼承的,而繼承行為發生在值計算之后,所以不同元素下的定義不一定構成循環引用,例如我們將最后一段定義改為div下的p:

:root {  --margin:20px;}div {  --padding: calc(var(--margin)-10px);  margin:var(--margin);  padding:var(--padding);  background:#f00;}div.cyclic p {   --margin: calc(var(--padding)+10px);   margin:var(--margin);   background:#0f0;}

在這個例子中,div.p的--可以正常計算得到20px,因為p在計算--時,--繼承自div,而div已經被計算為10px了。

更多示例

前面的例子中提到,CSS 自定義變量在取值時基本相當于文本替換,沒有類型的概念。這樣的操作在某些場景下也能出乎意料的方便,比如 CSS-Trick 上提到的例子:

意思相近的字組成詞語_custom什么意思_意思相近的兩字詞

button {  --h: 100;  --s: 50%;  --l: 50%;  --a: 1;    background: hsl(var(--h) var(--s) var(--l) / var(--a));}button:hover { /* Change the lightness on hover */  --l: 75%;}button:focus { /* Change the saturation on focus */  --s: 75%;}button[disabled] {  /* Make look disabled */  --s: 0%;  --a: 0.5;}

甚至有一種方法可以使用自定義變量作為開關,但請謹慎使用......

這里只是給出一些簡單的使用示例,相信很多同學在實際工作中,包括我們的項目中,都有自定義變量的情況。

04

關于動畫

自定義變量是 CSS 屬性,因此可以在動畫中使用。但是,由于它們沒有類型,CSS 解析器不知道如何應用動畫樣式。效果不會像您預期的那樣:

.color-div {  --angle: 0deg;  background: linear-gradient(var(--angle), red, yellow, blue, purple);  animation: rotate 5s ease-in-out both alternate infinite;}@keyframes rotate {  to {    --angle: 180deg;   }}

打開這個 demo 你會發現背景并沒有“動”,只是顏色跳動了一下。其實這應該符合預期,畢竟漸變算是圖片,本身不支持動畫。

其實一眼就能看懂這段 CSS 代碼想要表達什么,但是替換的方式讓自定義變量支持放在過渡動畫、動畫樣式中,其實并沒有什么用。不過這么明顯的問題,規范已經考慮到了,那么接下來我們看看他們是怎么解決這個問題的呢?

定義全局變量的另一種方法(注冊)

鑒于CSS自定義變量的語法非常松散,無法定義其值類型、是否繼承、及其初始值,這也導致無法很好實現動畫等問題,CSS增加了@來定義,或者更準確的說,使用(注冊)一個CSS自定義變量,可以設置其類型(或者其遵循的語法)、是否繼承、及其初始值-value。結合上面的例子,我們來簡單講解一下@的用法以及一些需要注意的地方。前面的例子只要加上這個定義聲明,就可以達到預期的效果了~

@property --angle { syntax: "";  inherits: false;??initial-value:?‘0deg’;}

同時@也有一個等價的接口可以調用,比如之前的聲明,可以使用如下方式實現:

CSS.registerProperty({  name: '--angle',??syntax:?'',??inherits:?false,??initialValue:?‘0deg’;});

從上面的示例和解釋來看,這些屬性的含義可能非常簡單。 但是,使用它們時需要注意以下幾點:

●首先,與大多數@語句一樣,@目前必須出現在CSS的最外層,不能嵌套在其他樣式聲明中,也不能位于最內層(但這種行為可能會改變,規范正在討論中)。它可以嵌套在條件@語句中,例如@media:

:root {  @property --primary-color {    /*不會生效*/  }}
@media (min-width: 1200px) { @property --width { /* 有效 */ }}

●其次,所有屬性都應設置,否則整個定義將被忽略。唯一的例外是,當屬性為*時,-value可以留空。不過,帶*的自定義變量的行為與普通定義基本相同。

●當需要填寫 -value 時,其值必須符合定義的語法,并且必須是計算獨立( )值,否則整個定義將被忽略。什么是“計算獨立”?簡單來說,就是不再依賴于其他 CSS 屬性值。例如,1em 不符合條件,因為它依賴于 font-size 的定義,var(--other-) 也不起作用,但像 1px 和 #F00 這樣的值是可以的。

@property --width {  syntax: "";  inherits: true;  initial-value: #f00; /* 不合定義語法的值,整個定義被忽略 */}@property --width {  syntax: "";  inherits: true;  initial-value: 1rem; /* 依賴根元素font-size,不符合條件,整個定義被忽略 */}

這里還要說一下-value,由于它的存在,var()的替換和之前略有不同,我們先來舉一個上一篇文章中的例子:

:root { --text-color: 16px; }p { color: blue; }p { color: var(--text-color); }
div { color: blue; }div { color: 16px; }

在這個例子中,如前所述,由于計算值時出現錯誤,定義未設置,因此 〈p〉 的顏色變為黑色。但是如果我們添加定義:

@property --text-color {  syntax: "";  inherits: true;  initial-value: #f00;}

這種情況下,在計算值的時候, --text-color: 16px; 并不符合聲明定義的語法,相當于 --text-color: unset;,所以結果為 --text-color: #f00; (即初始值),所以〈p〉 會顯示為紅色,而不是黑色。但請注意,驗證是在計算 div 值時發生的,而不是在解析 CSS 時發生的,所以如果我們將 --text-color 的定義改為如下形式,效果還是一樣:

:root {   --text-color: #0f0;   --text-color: 16px; /* 依舊是unset,而不是選擇讀取前一條,因為不是在解析時判斷的語法錯誤 */}

由于種種原因,規范選擇在解析時不做語法檢查,所以即使計算時有語法檢查,也和常規的解析錯誤不一致。如果這句話你還不太理解,回想一下前面錯誤檢查的例子中,div文字是藍色的。

另外要注意,對于有初始值的全局變量,當使用 var(--, ) 時,即使你手動將 --:; 替換為 var(--, ),也不會讀取相應 -value 定義的初始值。

可以填寫的類型有很多,也支持復合類型。前面的“”,或者“”和“>”等可以猜到的名字都是合法的值。詳細列表請看這里。注意引號是必須的,因為這個值需要類型。

關于多個同名聲明的優先級,如果CSS定義中存在同名的@聲明,則最后一個生效;但如果存在多個同名聲明,則其優先級最高,并且該方法不允許重復聲明相同的變量名。

最后,目前沒有辦法取消注冊變量,但規范提到可能會稍后添加此功能。

好了,本文到此結束。感謝您花時間閱讀。希望您閱讀完本文后對 CSS 自定義變量有更好的了解。

為您推薦

全國職稱英語等級考試歷年真題及全真模擬試卷,助你提高學習效率

全國職稱英語等級考試綜合類(C級)全真模擬試卷參考答案全國職稱英語等級考試綜合類(C級)全真模擬試卷題解全國職稱英語等級考試綜合類(B級)全真模擬試卷參考答案全國職稱英語等級考試綜合類(B級)全真模擬試卷題解全國職稱英語等級考試綜合類(A級)全真模擬試卷參考答案

2024-05-29 19:52

2014 年 6 月大學英語四級考試真題及答案(完整版)

why?上作答。上作答。

2024-05-28 21:18

2014 年中科大 843 真題詳解:OFT 與 OFS 的關系及周期序列計算

2014年中科大843真題詳解:利用OFT與OFS的關系由DFT計算OFS。對于周期信號來說DFS的系數是比起DFT的系數,比起DFS的系數就是放大了一倍,中科大這邊符號系統就是這樣,就是用最真實的、最正確的符號系統做的,就是要強調這一點。這是一個符號系統的問題,這邊也告訴你了符號系統了,對吧?

2024-05-28 08:15

六級聽力選項分布規律及大學英語四六級考試介紹

六級聽力的選項分布規律;三個題目的文章絕大多數三個題選項不同(16/18),六級四個題目的文章要么其中兩題選項相同(11/24),要么四題選項均不同。調整后,四級和六級的試卷結構和測試題型相同。

2024-05-28 07:21

英語四級十天輕松過!掌握這些超級技巧,聽力不再難

無須復習,只要十天英語四級就能過!偶還想提醒大家,千萬不要在30個詞匯題上浪費太多的時間,要知道每個題才0。如果你不幸遇到了簡短回答題,說實話,偶也沒有好辦法,這種題雖說千年難遇一次,但是偶認為這是四級考試中最有水平,最不好應對的題,出題人一定來自天外星球!

2024-05-27 21:32

windy是什么的知識,并解釋windy的英文含義

今天我將分享我關于windy是什么的知識,并解釋windy的英文含義。windy是什么意思擴展:Windy是一個英文單詞,意思是“有風的,有風的”。windy的中文是什么Windy是什么意思,windy是什么意思,英文介紹到此結束。

2024-05-26 15:25

加載中...
主站蜘蛛池模板: 芒康县| 呼伦贝尔市| 松桃| 邹平县| 江城| 宕昌县| 德格县| 黄浦区| 鸡泽县| 桐城市| 荣昌县| 青海省| 孟州市| 新乡市| 错那县| 高雄市| 家居| 兴安县| 耒阳市| 永嘉县| 沙河市| 体育| 宜都市| 荣昌县| 阿拉善左旗| 正镶白旗| 安庆市| 东辽县| 禄丰县| 谢通门县| 本溪市| 湘西| 宣城市| 边坝县| 珠海市| 盱眙县| 镇远县| 嘉义市| 青岛市| 佛冈县| 丰顺县|