CSS變量(自定義屬性)實踐指南

本文翻譯自:https://www.sitepoint.com/practical-guide-css-variables-custom-properties/

轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。

Sass和Less這樣的預處理器,讓我們的CSS代碼保持良好的結構和可維護性。像變量、混合(mixins)、循環控制等特性,增強了動態編寫CSS的能力,從而減少重復代碼,也加快了我們開發速度。

近年來,一些動態特性開始作為規范的一部分,出現在CSS語言中。CSS變量(CSS variables),或者用它的官方稱謂,叫作自定義屬性(custom properties),已經可用,并且有非常棒的瀏覽器支持,而CSS mixins也正在取得進展。

在本文,你將學會如何使用CSS變量,并把它集成到你的CSS開發流程中,讓你的樣式表更好維護,且減少重復。

讓我們現在就開始吧!

什么是CSS變量?

如果你曾使用過某種編程語言,那么你已經很熟悉變量這個概念了。變量用于存儲和更新你的程序所需要的值,以便使它運行。

例如,考慮下面的JavaScript代碼

let number1 = 2;
let number2 = 3;
let total = number1   number2;
console.log(total); // 5
number1 = 4;				
total = number1   number2;
console.log(total); // 7

nubmer1
和?
number2
是兩個變量,分別存儲著數字2和3。

total
同樣是變量,存儲著
number1
number2
之和。在這里它的值就是5。你可以動態地修改變量里的值,并在程序中使用它們。在上面的代碼中,我把
number1
的值更新為4,然后再進行求和。使用相同的變量,這個時候
total
里存儲的值就是5,而不再是7了。

使用變量的妙處在于,它可以讓你在一個地方存儲值,并且讓你在后面能以各種理由去更新它。在程序中,你不需要為不同的值再添加額外的字符表示:任何值的更新都發生在同一個地方。正如,在你定義的變量上

CSS在很大程度上是一種聲明式的語言,而缺少動態能力。你也許會認為,讓CSS擁有變量,幾乎讓上面的說法自相矛盾。如果前端開發僅僅是關于文字游戲,那可以這么說。幸運的是,Web的編程語言很像生活中的語言,它們會隨著周圍環境和實踐需要而不斷進化與適應。CSS也同樣如此。

簡單的說,變量已經成為CSS世界中激動人心的事實,并且你即將親自看到,對于這個厲害的新技術,學習和使用起來都非常直觀。

使用CSS變量有什么好處?

使用CSS變量的好處,跟在其他編程語言中使用變量的好處沒什么大的區別。

規范是這樣描述這一點的

使用CSS變量,給看似隨機的值加上富有信息的名字,從而使得大文件更容易閱讀和編輯,更少出錯。因為,你只需要在自定義屬性中改變一次值,所有應用了這個變量的地方都會自動跟著一起改變。W3C 規范

換句話說,通過給變量起一個對你來說在項目中有意義的名字,你能更容易的管理和維護你的代碼。例如,當你為項目中的主色調設置一個變量名

--primary-color
,那么你后面再修改這個主色調時,只需要改動一處,而不需要在不同位置的多個CSS文件中去手動修改多次值。

CSS變量和預處理器中的變量有什么不同?

你可能已經在CSS預處理器中嘗試過使用變量而帶來的好處了,比如Sass和Less。

預處理器讓你能設置變量,以及在函數、循環、數學計算等等地方中使用它們。這是否意味著CSS變量已經無關緊要了呢?

那可未必,主要是因為,CSS變量與預處理器中的變量其實是不同的東西。

這些不同基于一個事實:CSS變量是瀏覽器中直接可用的CSS屬性,而預處理中的變量是用于編譯成常規的CSS代碼,瀏覽器其實對它們一無所知。

這意味著,你可以在樣式表中,在內聯樣式中,在SVG的標簽中直接更新CSS變量,甚至可以在運行時用JavaScript直接修改它。而你是無法對預處理器中的變量做上面這些操作的。CSS變量開啟了一個充滿可能性的新世界大門。

不是說你必須要在兩者間做出選擇:沒有什么東西限制你,你可以同時使用CSS變量和預處理變量,并享有它們各自帶來的巨大好處。

CSS變量:語法

雖然本文為了簡潔,我使用了CSS變量(CSS variables)這個稱呼,但官方的規范把它們稱作作為級聯變量的CSS自定義屬性(CSS custom properties for cascading variables)。*CSS自定義屬性(CSS custom property)*的部分看起來像這樣:

--my-cool-background: #73a4f4;

在自定義屬性前添加雙橫線前綴,然后像給普通CSS設值一樣,給自定義屬性設值。在上面的代碼中,我給一個叫做

--my-cool-backgroud
的自定義屬性設置了一個顏色值。

而?級聯變量(cascading variable)?的部分,由通過

val()
來使用你的自定義屬性組成,開起來像這樣:

var(--my-cool-background);

自定義屬性作用于CSS選擇器中,

val()
可被當成一個真正的 CSS屬性一樣使用。

:root {
--my-cool-background: #73a4f4;
}
/* CSS文件的其他部分 */
#foo {
background-color: var(--my-cool-background);
}

上面的代碼片段把

--my-cool-background
這個自定義屬性的作用域定義在
:root
這個偽類中,這讓該自定義屬性能被全局訪問到(即在
<html>
標簽內部的任何地方)。然后,使用
val()
函數把 ID為foo的容器的
background-color
設置為自定義屬性的值,這時該容器就有了淺藍的背景色。

這還沒完。你可以用同樣的淺藍色,給多個HTML標簽的多種可以設置顏色值的地方設值,比如設置它們的

color
border-color
。方法很簡單,就是通過
var(--my-cool-background)
拿到自定義屬性的值,然后給合適的 CSS屬性設置上去。(當然,在事情變得復雜之前,我建議思考一下你的CSS變量命名規范):

p {
color: var(--my-cool-background);
}

示例1代碼,可點擊查看。

你還可以從通過利用CSS變量獲得另一個CSS變量的值。例如:

--top-color: orange;
--bottom-color: yellow;
--my-gradient: linear-gradient(var(--top-color), var(--bottom-color));

上面的代碼創建了一個

--my-gradient
變量,是一個漸變樣式,它的值被設為
--top-color
的值和
--bottom-color
的值組合的結果。現在,你可以在任何時候修改你的漸變樣式,僅僅是修改變量的值就可以了,而不再需要在樣式表里滿文件地去找用到這個漸變樣式地方。

示例2代碼

最后,你可以在CSS變量中加入一個或多個備用值(fallback value/s),例如:

var(--main-color, #333);	

上面的代碼中,

#333
是一個備用值。當自定義屬性值無效或未指定(unset)時,如果這時也沒有指定備用值,那么被繼承的(inherited)屬性值將會被使用。

CSS變量是區分大小寫的

與普通CSS屬性不同,CSS變量是區分大小寫的。

例如,

var(--foo)
var(--FOO)
是在求兩個不同的自定義屬性值,分別是
--foo
--FOO
的。

CSS變量受級聯關系影響

和普通CSS屬性一樣,CSS變量是可繼承的。例如,我們定義了一個屬性,值為

blue
:  

:root {
--main-color: blue;
}

當你給任意在

<html>
標簽里的元素指定
--main-color
變量時,它們都會繼承到
blue
這個值。

當你在另一個元素里,為改自定義屬性設置了一個新值時,那么所有該元素的子元素都會繼承那個新值。例如:  

:root {
--main-color: blue;
}
.alert {
--main-color: red;
}
p {
color: var(--main-color);
}
<--! HTML -->
<html>
<head>
<!-- head code here -->
</head>
<body>
<div>
<p>blue 的段落</p>
<div class="alert">
<p>red 的段落</p>
</div>
</div>
</body>
</html>

在上面的標簽中,第一個

p
段落會繼承到全局的
--main-color
值,它是藍色。

在div標簽中擁有

.alert
類的段落會是紅色,因為它的值繼承自局部作用域里的
--main-color

示例3代碼

知道目前這些規則差不多夠了。讓我們開始寫代碼吧!

如何在SVG中使用CSS變量

CSS變量和SVG配合得很好。你可以使用CSS變量去修改SVG中的樣式,以及和呈現相關的屬性。

舉個例子,假設你想讓你的SVG圖標能跟隨其所在父容器而擁有不同的顏色。你可以把CSS變量的作用域限定在父容器中,然后給變量設置想要的顏色,那么里面的圖標就會繼承父容器的顏色值。下面是相關代碼:

/* inline SVG symbol for the icon */
<svg>
<symbol id="close-icon" viewbox="0 0 200 200">
<circle cx="96" cy="96" r="88" fill="none" stroke="var(--icon-color)" stroke-width="15" />
<text x="100" y="160" fill="var(--icon-color)" text-anchor="middle" style="font-size:250px;">x</text>
</symbol>
</svg>
/* first instance of the icon */
<svg>
<use xlink:href="#close-icon" />
</svg>

上面的代碼使用了

<symbol>
標簽,它讓你創建一SVG圖形的不可見的版本。然后再使用
<use>
標簽生成一個可見的副本。這種方法可以讓你根據自己的喜好創建任意多個自定義的圖標,也就是通過它的ID(
#close-icon
)指向那個
<symbol>
。這比一遍又一遍地寫重復的代碼創建圖形更加簡便。如果你想提高這方便的技術,Massimo Cassandro在他的 Build Your Own SVG Icons中提供了一個快速教程。

注意到SVG symbol中,circle元素里的

stroke
屬性和text元素里的
fill
屬性:它們都使用了CSS變量,這里是
--icon-color
。它被定義在
:root
CSS文件的選擇器中,像這樣:  

:root {
--icon-color: black;
}

這是當前圖標看起來的樣子:

這時,如果你把同樣的SVG圖標放在不同的父容器中,并且在父容器上,給你的CSS變量設置各自的局部值,那么你就會得到不同顏色的圖標,并且不用給你的樣式表添加多余的規則。這很酷!

為了展示這一點,我們把同樣的圖標放在一個有

.success
類的div里:

<!-- html -->
<div class="success">
<svg>
<use xlink:href="#close-icon" />
</svg>
</div>

現在,讓

--icon-color
變量局部化,即把它放在
.success
中,并設置一個
green
值。我們來看看發生的變化:

/* css */
.success {
--icon-color: green;
}

這個圖標的顏色就變成了綠色:  

  

來看看一個完整的示例吧:?示例4代碼。

如何在
@keyframes
中使用CSS變量

CSS變量可以在CSS動畫中使用,即可用于常規HTML元素,也可以用于內聯的SVG。只需要記得,你得知道讓什么元素動,把它視為目標元素,然后創建對該目標元素的選擇器,在選擇器的作用范圍中定義你的CSS變量,然后,使用

val()
獲取這些變量,把它們設置到
@keyframes
代碼塊中。

例如,讓SVG中

.bubble
類里面的
<ellipse>
元素動起來,你的CSS可能會看起來像這樣:

.bubble {
--direction-y: 30px;
--transparency: 0;
animation: bubbling 3s forwards infinite;
}
@keyframes bubbling {
0% {
transform: translatey(var(--direction-y));
opacity: var(--transparency);
}
40% {
opacity: calc(var(--transparency)   0.2);
}
70% {
opacity: calc(var(--transparency)   0.1);
}
100% {
opacity: var(--transparency);
}
}

注意到這是如何借助CSS的

calc()
,并用
var()
函數進行計算的。它們增強了你代碼的靈活性。

這個例子簡潔的地方在于,利用CSS屬性,你可以簡單的修改相應選擇器里變量值而調整動畫,而不需要挨個去查找

@keyframes
里的屬性了。

這里有個完整的例子供你體驗:示例5代碼。  

如何通過JavaScript操作CSS變量

另一個超級酷的事情就是,你可以直接通過JavaScript代碼訪問CSS變量。

假設在你的CSS文件中,有一個叫做

--left-pos
的變量,作用在
.sidebar
選擇器中,值為
100px

.sidebar {
--left-pos: 100px;
}

那么,通過JavaScript獲取

--left-pos
值,會像下面這樣:

// 緩存你即將操縱的元素
const sidebarElement = document.querySelector('.sidebar');
// 緩存sidebarElement的樣式于cssStyles中
const cssStyles = getComputedStyle(sidebarElement);
// 獲取 --left-pos CSS變量的值
const cssVal = String(cssStyles.getPropertyValue('--left-pos')).trim();
// 將CSS 變量的值打印到控制臺: 100px
console.log(cssVal);

如果想通過JavaScript設置CSS變量的值,你可以像這樣:

sidebarElement.style.setProperty('--left-pos', '200px');

上面的代碼將sidebar元素中

--left-pos
變量的值設置為
200px

請看看CodePen中的如下示例,你可以交互式地點擊側邊欄,修改blend mode屬性和背景色。這些實現只用到了CSS變量和JavaScript。

示例6代碼。

CSS變量的瀏覽器支持

除了IE11(它不支持CSS變量),所有主流瀏覽器都對CSS變量有全面地支持。

對于不支持CSS變量的瀏覽器,一個變通的方案是使用具有虛擬查詢條件(dummy conditional query)的

@supports
代碼塊:

section {
color: gray;
}
@supports(--css: variables) {
section {
--my-color: blue;
color: var(--my-color, 'blue');
}
}

考慮到

@supports
在IE/Edge里也起作用,上面的方法是可行的。如果你在
val()
函數中使用了備用值,那么你的代碼將更加可靠,它能在兼容性不好的瀏覽器中實現優雅降級。

對于上面的代碼,在Chrome和其他支持CSS變量的瀏覽器中,

<section>
標簽里的文本將是藍色:

IE11中,由于它不支持CSS變量,頁面將顯示灰色文本:

  

可以查看在線的示例7

此方法的一個缺點是,如果你大量使用CSS變量,而那些不支持CSS變量的瀏覽器在你的項目中有很高的適配優先級,那么相應的代碼會變得很復雜,對于維護來說,甚至是噩夢。

在這種情況下,你可以選擇使用帶有cssnext的PostCSS,它能讓你在CSS代碼中使用最新的特性,并且讓原本不支持這些屬性的瀏覽器,也能運行這些代碼(有點像JavaScript轉換器做的事情)。

備注:這里可下載本文所有示列代碼

?

本文轉載于:猿2048https://www.mk2048.com/blog/blog.php?id=hajkh1j&title=CSS變量(自定義屬性)實踐指南

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/370928.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370928.shtml
英文地址,請注明出處:http://en.pswp.cn/news/370928.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

避免使用FOR –反假戰役

您是否想知道FOR如何影響您的代碼&#xff1f; 他們如何限制您的設計&#xff0c;更重要的是如何將您的代碼轉換為無人為含義的多行代碼&#xff1f; 在這篇文章中&#xff0c;我們將看到如何將for的簡單示例&#xff08;由Francesco Cirillio提供- 反if活動&#xff09;轉換為…

ffmpeg-win32-v3.2.4 下載_MVBOX下載|MVBOX 7.1.0.4官方版

還是要強調一句&#xff0c;現在市面上很多盜版或者免費的軟件&#xff0c;都給一些黑客留下了暗門&#xff0c;所以大家還是支持正版比較好&#xff0c;不要貪圖便宜使用盜版軟件造成不好的后果。MVBOX播放器功能介紹1、在線卡拉OK2、虛擬攝像頭3、畫面調色板4、攝像頭摳像5、…

linux重啟鼠標鍵盤服務,Linux 關閉服務后 鼠標 鍵盤用不了

大部分情況下我們做實驗都是使用虛擬機&#xff0c;但是個人比較本實在太老了&#xff0c;性能有限&#xff0c;所以虛擬機里面的系統啟動神慢&#xff0c;怎么辦&#xff1f;把系統中自己用不到的服務全部關閉掉唄&#xff0c;如下for i in chkconfig --list | awk {print $1}…

拖拽功能-jquery

<!DOCTYPE html><html lang"en"><head> <meta charset"UTF-8"> <title>拖拽</title> <style> .nav { width: 200px; height: 200px; border: 1px solid blac…

PNG,GIF,JPG的區別及如何選

GIF&#xff1a; 1&#xff1a;256色 2&#xff1a; 無損&#xff0c;編輯 保存時候&#xff0c;不會損失。 3&#xff1a;支持簡單動畫。 4&#xff1a;支持boolean透明&#xff0c;也就是要么完全透明&#xff0c;要么不透明 JPEG&#xff1a; 1&#xff1a;millions o…

餓了么商家電腦版_餓了么企業版榮膺“2020中國十大影響力人力資源品牌”大獎...

11月6日&#xff0c;由MeetHR GROUP主辦的2020大中華地區HRVP高峰論壇在上海落幕。餓了么企業版憑借自身產品在人力資源管理與服務方面的創新實踐&#xff0c;榮獲“2020 中國十大影響力人力資源品牌(薪酬福利類)”殊榮。本次評選&#xff0c;據主辦方介紹&#xff0c;旨在激勵…

用信號量鎖定:一個例子

并發是帶來有趣挑戰的一個方面。 如果處理不當&#xff0c;會導致種族狀況&#xff0c;這會使人們感到困惑&#xff0c;因為這些問題有時會突然出現&#xff0c;并且有時會完美無缺地發揮作用。 當處理訪問公共資源的并發線程時&#xff0c;Java語言提供了許多處理競爭條件的方…

navicat連接linux遠程數據庫,使用Navicat forMySql遠程連接Linux 系統上的數據庫

使用Navicat for MySql遠程連接Linux 系統上的數據庫解決mysql"Access denied for userrootIP地址"問題1.問題說明&#xff1a;在MYSQL 中&#xff0c;用遠程軟件登陸服務器&#xff0c;有時出現&#xff1a;Access denied for user rootlocalhost出現這種問題&#…

HTTPS 通俗簡介

為什么需要HTTPS 9個問題搞懂 https 來源 HTTP是明文傳輸的&#xff0c;也就意味著&#xff0c;介于發送端、接收端中間的任意節點都可以知道你們傳輸的內容是什么。這些節點可能是路由器、代理 等。 舉個最常見的例子&#xff0c;用戶登陸。用戶輸入賬號&#xff0c;密碼&am…

CSS Modules入門教程

為什么引入CSS Modules 或者可以這么說&#xff0c;CSS Modules為我們解決了什么痛點。針對以往我寫網頁樣式的經驗&#xff0c;具體來說可以歸納為以下幾點&#xff1a; 全局樣式沖突 過程是這樣的&#xff1a;你現在有兩個模塊&#xff0c;分別為A、B,你可能會單獨針對這兩…

單點登錄(一):思考

單點登錄&#xff08;后文簡稱&#xff1a;sso&#xff09;的定義是在多個應用系統中&#xff0c;用戶只需要登錄一次就可以訪問所有相互信任的應用系統&#xff08;摘自百度百科&#xff09;。整個流程中涉及到的角色有&#xff1a;用戶。應用服務器&#xff0c;即業務系統。單…

熱電偶校驗儀_熱電偶校驗方法_熱電偶的使用方法及維修經驗

一、遵照儀表接線圖進行準確接線通電后&#xff0c;儀表先是顯示儀表的熱電偶分度號&#xff0c;接著顯示儀表量程范圍&#xff0c;再測儀表顯示設定溫度&#xff0c;數顯儀表顯示測量溫度。若儀表數碼管顯示不是發熱體的溫度&#xff0c;而顯示“OVER”、“0000”或“000”等狀…

linux svn checkout密碼,linux的svn之checkout命令

linux的checkout命令是linux的svn的常用命令之一。下面由秋天網 Qiutian.ZqNF.Com小編為大家搜集整理了linux的svn之checkout命令的相關知識&#xff0c;希望對大家有幫助!linux的svn之checkout命令常用檢出命令&#xff1a;svn co http://路徑(目錄或文件的全路徑) [本地目錄…

Java 7:滿足Fork / Join框架

JSR-166&#xff08;y&#xff09;是Java 7中包含的此新功能的正式名稱。如果您發現名稱中有一個“ y”&#xff0c;這是因為自Java 5起就添加了JSR-166&#xff08;并發實用程序&#xff09; &#xff0c;但它不會就此停止&#xff0c;因為已經有計劃在JSR-166&#xff08;e&a…

css3總結之居中

居中在前端布局上很常見&#xff0c;也很常用&#xff0c;也是最基本的技巧。居中效果在方向控制上基本可以分解成水平居中&#xff0c;垂直居中和水平垂直居中。 針對調整的元素不同&#xff0c;具體的處理方式上有些差異。這里我們先不講絕對定位下的居中&#xff0c;絕對定位…

PHP進程及進程間通信

一、引言 進程是一個具有獨立功能的程序關于某個數據集合的一次運行活動。換句話說就是&#xff0c;在系統調度多個cpu的時候&#xff0c;一個程序的基本單元。進程對于大多數的語言都不是一個陌生的概念&#xff0c;作為"世界上最好的語言PHP"當然也例外。 二、環境…

福州java培訓哪里好_南通java培訓哪家好

渡課IT教育成立于2006年&#xff0c;14年來&#xff0c;我們累計輸送學員達 6000 &#xff0c;其中南通地區輸送50%&#xff0c;上海 40%&#xff0c;其他地區 10%&#xff0c;學員1年后的平均薪水達 9860 元&#xff1b;受到1000用人單位的贊譽與支持。Java開發的需求量在北上…

Linux 服務器注意事項

1.創建時 數據文件一定分盤掛載 2.LVM 虛擬磁盤卷是否創建 有爭議&#xff1f;&#xff1f;&#xff1f;3.hosts 文件 最好添加本機映射 主機名 127.0.0.1 4.iptables 開啟轉載于:https://www.cnblogs.com/centos2017/p/7896681.html

linux 查看下掛磁盤,linux下磁盤掛載與查看

df查看系統分區和使用情況使用方法&#xff1a;df-h(自動按照大小做單位適應顯示)df-i(查看iNode使用情況)free查看..LABELdefaults默認選項&#xff1a;rw (可讀寫)sudi (加此選項后則該分區可為文件加s權限&#xff1b;如不需要則寫為nosuid)dev(可以解析該分區下的塊…

研究僵局–第2部分

調查死鎖時最重要的要求之一就是要研究死鎖。 在我的上一個博客中&#xff0c;我編寫了一個名為DeadlockDemo代碼&#xff0c;該代碼使用一堆線程在一系列銀行帳戶之間轉移隨機數&#xff0c;然后陷入僵局。 該博客運行該代碼以演示獲取線程轉儲的幾種方法。 線程轉儲只是一個…