我總結的 CSS 變量知識點

攝影 | Eliott Reynajavascript

最近讀到一篇文章《Everything you need to know about CSS Variables》,讓我對 CSS 變量有了新的認識。下面將整理出來的跟本身感悟的地方與你們分享,但願能幫助到對 CSS 變量還只知其一;不知其二的同窗。css

答疑

1、爲何 CSS 變量還稱爲「自定義屬性(custom properties)」?

咱們回憶 CSS 變量的使用方式:html

span {
    /* 局部變量 --color */
    --color: gold;
    color: var(--color);
}
複製代碼

聲明 CSS 變量的時候,發現跟使用普通屬性是同樣的,這裏說的「同樣」是指:使用的位置同樣,而且使用的方式也同樣。java

只不過跟普通屬性相比,CSS 變量多了兩個連字符 -- 做爲前綴,本質上就是個屬性。並且這類屬性都是開發者本身起的,屬性值也是咱們設置的,天然就是「自定義屬性」了。瀏覽器

不過特殊的地方在於,咱們可使用 var() 函數解析出這類屬性的屬性值:ide

color: var(--color);
/* 至關於 */
color: gold;
複製代碼

還有一點,CSS 變量既然是屬性,那麼就能夠像行內樣式那樣使用:函數

<span style="--color: gold; color: var(--color);">這段文本是金色的</span>
複製代碼

文章後面「使用 JS 操做 CSS 變量」一節,就是基於此種寫法實現的。以後會講到,我們先繼續往下看。ui

2、全局變量和局部變量

全局變量是這樣聲明的:spa

:root {
    --color: gray;
}
複製代碼

:root 僞類命中的是文檔根元素 <html>,也就說3d

:root {
    --color: gray;
}
/* 至關於 */
html {
    --color: gray;
}
複製代碼

根元素是文檔的最頂層元素,在它下面聲明的變量就是全局變量。對應的,不是全局的變量就是局部變量。

<style> :root { /* 全局變量 --color */ --color: gray; } p { /* 局部變量 --color */ --color: gold; color: var(--color); } </style>

這段文本是灰色的,<span>這段文本是金色的</span>
複製代碼

與 JS 做用域相似的是,局部變量會覆蓋全局中的同名變量。所以上面 <span> 裏的文本是金色的。

3、var() 解析出來的結果只能做爲屬性值使用

下面這樣寫是不行的:

.mt-20px {
    --mt: margin-top;
    var(--mt): 20px; /* × 這種寫法是錯誤的 */
}
複製代碼

咱們想要多是這種結果:margin-top: 20px,但觀察發現,瀏覽器並不會解析 var(--mt),並且提示這是一個未知屬性名。

下面這樣寫就沒有問題了:

.mt-20px {
    --20px: 20px;
    margin-top: var(--20px); /* √ 這樣寫就沒問題了 */
}
複製代碼

4、var() 的回退值(fallback)

var() 功能符,還接受第二個參數,表示一個回退值——當變量不能成功解析時,就會使用這個回退值。

.header {
    color: var(--header-color, blue);
}
複製代碼

上面代碼中,若是 --header-color 沒有聲明的話,就會使用回退值 blue,做用有點相似於 JS 函數中的參數默認值。

5、使用 calc() 作數學運算

若是聲明的變量值中包含數學運算,就要包裝在 calc() 函數中。不然是無效運算。

像下面這種寫法就不對:

.font-40px {
    --size: 20px * 2; /* × 錯誤的寫法 */
    font-size: var(--size);
}
複製代碼

在瀏覽器中觀察,不會看見顯式的報錯,但 font-size 的最終解析值還是默認的 16px

這種錯誤寫法在瀏覽器中並不會顯式報錯

`font-size` 的最終的解析值還是 `16px`

須要這樣寫:

.font-40px {
    --size: calc(20px * 2); /* √ 正確的寫法 */
    font-size: var(--size);
}
複製代碼

calc() 函數的引入,爲在 CSS 中進行各類不一樣單位的混合數值運算(加、減、乘、除),帶來了極大的便捷:

.example {
    /* 加 */
    width: calc(100% + 1em);
    /* 減 */
    width: calc(100% - 80px);
    /* 乘 */
    width: calc(100% * .5);
    /* 除 */
    width: calc(100% / 6);
}
複製代碼

這裏拋磚引玉,更多的使用細節能夠查看 MDN 上的文檔

6、使用 JS 操做 CSS 變量

JS 操做 CSS 變量的原理,是使用 DOM 對象的 style 屬性,它是一個 CSSStyleDeclaration 類型的對象。

咱們以前可能作過這樣的操做:

document.body.style.color = 'gold'
複製代碼

color 是標準屬性,能夠直接使用這種方式設置。CSS 變量則屬於非標準屬性,使用這種方法就不會起做用:

// × 錯誤的寫法,由於 --color 並非標準屬性
document.body.style['--color'] = 'gold'
複製代碼

CSSStyleDeclaration 上提供了一個 setProperty() 方法,能夠用來設置非標準屬性。語法以下:

style.setProperty(propertyName, value, priority);

所以,咱們能夠這麼作:

document.body.style.setProperty('--color', 'gold');
複製代碼

執行結果以下:

這樣,我們就能經過 JS 操做 CSS 變量了。

實踐

CSS 變量的使用,在必定程度上改變了咱們書寫、組織代碼的形式。其原理在於,咱們可以修改已有變量的值。

下面我舉兩個比較有表明性的案例:

  1. 主題按鈕
  2. 元素的 transform 變換

主題按鈕

咱們有四個主題色的按鈕,在不一樣的場景下使用。使用之前的寫法,是經過覆蓋屬性的方式實現的:

.btn {
    color: #333;
    background-color: #eee;
    border: 0;
    padding: .5rem;
    cursor: pointer;
}

.btn-success {
    color: #fff;
    background-color: green;
}

.btn-error {
    color: #fff;
    background-color: red;
}

.btn-warning {
    background-color: orange;
}
複製代碼

若是使用變量,就不須要覆蓋屬性,直接修改變量值便可。

.btn {
    color: var(--btn-color, #333);
    background-color: var(--btn-bg-color, #eee);
    border: 0;
    padding: .5rem;
}

.btn-success {
    --btn-color: #fff;
    --btn-bg-color: green;
}

.btn-error {
    --btn-color: #fff;
    --btn-bg-color: red;
}

.btn-warning {
    --btn-bg-color: orange;
}
複製代碼

demo 地址查看這裏:codepen.io/zhangbao/pe…

元素的 transform 變換

先看看最終的效果圖:

demo 地址:codepen.io/zhangbao/pe…

實現原理是這樣的:咱們在拖拉 Range Input 的時候,獲取當前的 value 值,設置爲變量 --slider 的值,.color-boxes 使用了此變量設置自身的 Y 軸偏移度。

涉及到的核心代碼以下:

CSS:

.color-boxes {
    transform: perspective(500px) rotateY( calc(var(--slider) * 1deg));
}
複製代碼

JS

const range = document.querySelector('.booth-slider')

range.addEventListener('input', handleSlider)
function handleSlider (e) {
  document.documentElement.style.setProperty('--slider', e.target.value)
}
複製代碼

嗯,很神奇。

最後

本篇文章是我在看了一篇技術文章後總結的知識點,並加上了本身的一些感悟。若是看完後幫到了你,我將感到萬分榮幸!😁

(完)

相關文章
相關標籤/搜索