CSS自定義屬性?聽着怎麼那麼神奇呢,屬性還能夠自定義,那不是能夠放肆地玩耍?我本身定義的屬性瀏覽器都能認識?css
其實CSS自定義屬性還有不少小名,好比CSS變量、原生變量、CSS自定義屬性級聯變量,這些指的都是同個東西。html
說到變量,在SCSS\LESS等CSS預處理器中你們都已經常常運用,說來有幾點好處:ios
一、能使用顏色變量統一風格;
二、能夠採用一致的組件屬性,包括佈局和定位等;
三、避免代碼冗餘。css3
那既然SCSS就能作到的東西,咱們還有這個所謂的CSS自定義變量幹什麼呢?人家天然有它的獨到之處。web
一、好比能夠在運行時改寫,具有動態性;
二、好比方便使用JS讀取和改寫;
三、好比可繼承、可組合、同時具備做用域。小程序
在這幾個方面,預處理器徹底被CSS自定義變量KO了。瀏覽器
語法很簡單,分紅兩步,聲明變量和使用變量。bash
聲明變量使用的是--
前綴。wordpress
:root{
--*: xxxx;
/* --variety-name: variety-value; */
}
複製代碼
這裏須要注意幾個點:函數
:root
匹配的就是HTML中的<html>
元素,具備最高的權重,:root
聲明的變量就是全局變量;--color
和--Color
是兩個變量;:root{
--黑色:#000;
}
body{
background: var(--黑色);
}
複製代碼
手賤如我試了一下,真的能夠識別。可是,爲了世界和平請答應我不要這麼寫。
很簡單,就是咱們很熟悉的var
關鍵字。
/* 定義變量 */
:root{
--*: #000;
/* 例如 --color-bg: #000; */
}
/* 使用變量 */
body{
background: var(--*);
/* 例如 background: var(--color-bg); */
}
複製代碼
還有一種設置默認值的使用,就是在變量名稱後面,加上一個默認值。
.div{
background: var(--變量名稱,[默認值]);
/* 例如 background: var(--color-bg, #000); */
}
複製代碼
也就是說,當這個變量沒有被聲明過的話,就會使用默認值,不至於沒着沒落的。
注意這裏的狀況是變量沒有被聲明過,要是變量是聲明過的,可是使用起來是不合法的,那麼就會採用原來屬性的缺省默認值,並非後面這個你設定的默認值。
p{
background-color: var(--color, #000);
/* --color沒有聲明過,因此這裏的p元素背景顏色時候用了默認值#000 */
}
複製代碼
div{
--color: 20px;
background-color: var(--color, #000);
/* 很明顯,background-color: 20px;是有語法錯誤的,因此這裏div的背景色爲透明,取的是這個屬性的默認值 */
}
複製代碼
一、若是你須要定義一個全局的變量,那麼能夠放在
:root
根元素下面;
二、若是隻須要在部分元素/組件下使用,就定義在相關的類下面;
三、另外還能夠在@media
媒體查詢中或者:hover
等僞類中使用。
理解了做用域,那麼權重也是一樣的道理,由於CSS自定義變量是能夠繼承的,因此權重跟咱們平時的屬性權重理解是同樣的。
這裏引用一下張鑫旭大神的例子給你們出道題。
:root{
--color: purple;
}
div{
--color: green;
}
#alert{
--color: red;
}
*{
color: var(--color);
}
複製代碼
<p>請問我是什麼顏色</p>
<div>請問我是什麼顏色</div>
<div id="alert">
請問我是什麼顏色
<p>請問我是什麼顏色</p>
<p style="--color: grey;">請問我是什麼顏色</p>
</div>
複製代碼
答案以下:
除了上述的一些用法,CSS自定義變量也可使用calc()
函數進行計算,或者進行字符串拼接。
這裏舉了三個例子,具體的說明在註釋中。
p{
--fz: 50;
font-size: var(--fz)px;
/* 不要太天真,這樣是錯的 */
}
複製代碼
p{
--fz: 50;
font-szie: calc(var(--fz) * 1px);
/* 若是你必定要這麼用,可使用calc計算函數 */
}
複製代碼
p::after{
--text: "hellp";
content: var(--text) " word";
/* 可是字符串的拼接是能夠實現的 */
}
複製代碼
固然,變量不止能夠直接使用,直接或者經過計算把值傳遞給另外一個變量也是可行的。
p{
--fz: 20px;
--fz-lg: var(--fz);
font-size: var(--fz-lg);
/* 直接傳遞 */
}
複製代碼
p{
--fz: 20px;
--fz-lg: calc(var(--fz) * 1.5);
font-size: var(--fz-lg);
/* 經過計算後傳遞 */
}
複製代碼
讀:getPropertyValue( )
寫:setProperty( )
好比說,你在:root
上定義了一個color變量,用於設置頁面的主題色,那麼經過下面的JS,你就能夠很簡單地改變color變量的值,從而改變頁面的主題色。換個皮膚,so easy。
// 讀取數據
const rootStyles = getComputedStyle(document.documentElement);
const varValue = rootStyles.getPropertyValue('--color').trim();
// 改寫數據
document.documentElement.style.setProperty('--color', value);
複製代碼
固然用處不止用來換膚,充分發揮你的想象力,看看CSS變量與JS的結合能產生什麼樣奇妙的效果~附上大漠老師的小DEMO。
介紹了這麼多,那麼CSS自定義變量到底都在什麼場景下應用呢?
最強的應用固然是一鍵換膚啦!
通常狀況下,咱們如果想根據不一樣的合做方或者不一樣的應用更換主題顏色,通常使用預處理器先定義一個全局主題顏色,如:
$theme-color: #f00;
button{
background: $theme-color;
}
複製代碼
最後編譯獲得一個定製的CSS文件,如:
button{
background: #f00;
}
複製代碼
這樣咱們就能夠經過引入這個特殊的CSS文件,獲得一套主題色爲紅色的頁面樣式。
第一種形式適用於,功能通用可是最後根據配置輸出一個產品的獨立管理臺、一個獨立小程序等,這樣用本身一套獨有的CSS文件就很方便。
可是若是咱們提供一個通用的產品去接入不一樣的合做方,接入方都有定製主題的需求,就能夠選擇預處理器或CSS自定義屬性。
/* 預處理器方式,先定義不一樣的主題色 */
$theme-color-a: #f00;
$theme-color-b: #0f0;
/* 在頁面層級最外層加上定製的類名,類名中全部樣式都須要從新覆蓋一遍 */
.project-a{
button{
background: $theme-color-a;
}
a{
color: $theme-color-a;
}
}
.project-b{
button{
background: $theme-color-b;
}
a{
color: $theme-color-b;
}
}
/* 或者在媒體查詢中須要重置樣式 */
$fz-sm: 12px;
$fz-md: 14px;
button{
font-size: $fz-sm;
}
a{
font-size: $fz-sm;
}
@media (min-width: 375px){
button{
font-size: $fz-md;
}
a{
font-size: $fz-md;
}
}
複製代碼
:root{
--FZ: 12px;
}
/* 照常寫一套樣式 */
button{
background: var(--THEME-COLOR, #fff);
}
a{
color: var(--THEME-COLOR, #fff);
}
/* 根據不一樣的接入方設置主題色 */
.project-a{
--THEME-COLOR: #f00;
}
.project-b{
--THEME-COLOR: #0f0;
}
@media (min-width: 375px){
:root{
--FZ: 14px;
}
}
複製代碼
這種需求在CSS預處理器中沒法實現一個沒有複製代碼的方案,老是須要覆蓋實現的值和規則,這也常常會致使CSS冗餘。
使用CSS自定義屬性,解決方案是儘量的簡潔,也避免複製和粘貼代碼,由於只要從新定義變量的值,不須要去覆蓋一次樣式。
第二種方式中兩個方式的區別則是,預處理器中變量的做用域是沒法繼承的,而CSS自定義變量則相對靈活,這樣一旦接入方多了以後,兩種方式的代碼量就會有質的區別。
以上兩種方式都仍是直接把主題色配置在CSS中。可是若是須要接入管理臺,讓合做方直接在管理臺設置主題色的話,預處理器這種靜態的方式就直接退出了競爭,CSS自定義屬性的絕對優點就出來了。
:root{
--THEME-COLOR: #fff;
}
button{
background: var(--THEME-COLOR);
}
a{
color: var(--THEME-COLOR);
}
複製代碼
let value = #f00; //或者經過請求獲取配置的主題色
document.documentElement.style.setProperty('--THEME-COLOR', value);
複製代碼
第三種方式則很是靈活,咱們能夠經過管理臺或者其餘配置的方式,傳遞合做方主題色,一鍵應用便可。
歷史性的時刻誕生了,今後接入就是分分鐘的事,直接讀取管理臺的配置,更改CSS自定義屬性。來個小DEMO體驗一下吧。
預處理器提供了不少高級的顏色方法,能夠實現顏色的高亮、變暗或去飽和等等;
$color: #f00;
.lighten{
background: lighten($color,10%);
}
.darken{
background: darken($color,10%);
}
.desaturate{
background: desaturate($color,10%);
}
複製代碼
這樣編譯出來的結果就是
.lighten{
background: #ff3333;
}
.darken{
background: #cc0000;
}
.desaturate{
background: #f20d0d;
}
複製代碼
這些方法沒法直接使用在CSS自定義屬性中,可是咱們能夠經過rgb( )或者hsl( )來調整主題顏色的色調或亮度。
rgb顏色變亮變暗的原理相對簡單,只需修改--COLOR-R
/--COLOR-G
/--COLOR-B
的值,利用calc函數對rgb的值進行線性增減便可。
:root{
--COLOR-R: 25;
--COLOR-G: 153;
--COLOR-B: 112;
--DARKEN: 30; // 加深程度
--LIGHTEN: 30; // 變亮程度
--THEME-COLOR: rgb(var(--COLOR-R), var(--COLOR-G), var(--COLOR-B));
--THEME-COLOR-DARKEN: rgb(calc(var(--COLOR-R) - var(--DARKEN)), calc(var(--COLOR-G) - var(--DARKEN)), calc(var(--COLOR-B) - var(--DARKEN)));
--THEME-COLOR-LIGHTEN: rgb(calc(var(--COLOR-R) + var(--LIGHTEN)), calc(var(--COLOR-G) + var(--LIGHTEN)), calc(var(--COLOR-B) + var(--LIGHTEN)));
}
複製代碼
rgb咱們可能相對熟悉,可是hsl用得比較少,下面簡單介紹一下hsl的原理,詳細內容請點擊連接。
與RGB使用的三色光不一樣,HSL一樣使用了3個份量來描述色彩,HSL色彩的表述方式是:H(hue)色相,S(saturation)飽和度,以及L(lightness)亮度。
HSL的H(hue)份量,表明的是人眼所能感知的顏色範圍,這些顏色分佈在一個平面的色相環上,取值範圍是0°到360°的圓心角,每一個角度能夠表明一種顏色。
HSL的S(saturation)份量,指的是色彩的飽和度,它用0%至100%的值描述了相同色相、明度下色彩純度的變化。數值越大,顏色中的灰色越少,顏色越鮮豔,呈現一種從理性(灰度)到感性(純色)的變化。
HSL的L(lightness)份量,指的是色彩的明度,做用是控制色彩的明暗變化。它一樣使用了0%至100%的取值範圍。數值越小,色彩越暗,越接近於黑色;數值越大,色彩越亮,越接近於白色。
通常來講,咱們須要按鈕在hover狀態時加深顏色,此時應用的原理是將顏色的hsl值中的L也就是亮度調低。
:root{
--COLOR-H: 29;
--COLOR-S: 100;
--COLOR-L: 50;
--DARKEN: 0.15;
--THEME-COLOR: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * 1%));
--THEME-COLOR-DARKEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 - var(--DARKEN)) * 1%));
--THEME-COLOR-LIGHTEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 + var(--DARKEN)) * 1%));
}
複製代碼
若是不經過改變色值來改變顏色的話,能夠選擇遮上一個半透明的蒙層來改變顏色,加深顏色則選擇黑色半透明蒙層,提亮顏色則選擇白色半透明蒙層。
.button_color{
position: relative;
color: #fff;
background: var(--THEME-COLOR);
border: 1px solid var(--THEME-COLOR);
&:after{
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: all 0.2s;
}
/* 黑色半透明蒙層 */
&:hover:after{
background: rgba(0,0,0,0.05);
}
/* 白色半透明蒙層 */
&.lighten:hover:after{
background: rgba(255,255,255,0.1);
}
}
複製代碼
目前CSS自定義變量的兼容性仍是比較可觀的,新的主流瀏覽器都支持。
PC端主要是IE這塊硬石頭,而移動端則主要是低端機型系統例如ios9.2及如下/安卓4.4及如下不支持,這樣的兼容性已經足以容許讓咱們在項目中開始使用CSS自定義屬性,並對一些低端版本進行下降兼容處理。
對於不支持的瀏覽器能夠採用下列兼容方式:
直接使用普通的屬性定義,兼容全部的瀏覽器,保證顯示正常。
button{
background: #F00;
/* 默認顏色,若不支持CSS自定義屬性則應用該默認顏色 */
background: var(--THEME-COLOR, #F00);
/* 在實踐中發現有些機型雖然能識別到CSS自定義變量可是沒法獲取正確顏色,只能獲取到默認值 */
}
複製代碼
低端機型也沒法正確識別@supports,@supports的兼容性只比CSS自定義變量好一丟丟。
@supports ( (--a: 0)) {
/* supported */
}
@supports ( not (--a: 0)) {
/* not supported */
}
複製代碼
const isSupported =
window.CSS &&
window.CSS.supports &&
window.CSS.supports('--a', 0);
if (isSupported) {
/* supported 引入支持自定義變量的CSS,容許更改CSS自定義變量 */
} else {
/* not supported 引入兼容的CSS文件 */
}
複製代碼
calc()
運算可能不能工做;calc()
運算時,最好能提供默認值:calc(var(--base-line-height, 0) * 1rem)
;@media screen and (min-width: var(--desktop-breakpoint) ) {
};
複製代碼
url( var(--image-url) )
,不會生效;html
,並經過上述方法修改自定義屬性的值;.container{
--THEME-COLOR: #f00;
}
複製代碼
<view class="container" style="--THEME-COLOR: #0f0;">
<!-- 該結構下的元素,重置爲行內樣式的主題色 -->
</view>
複製代碼