最一開始,其實我是想用 js 更改 scss 變數內容來達到網站更換顏色的效果,查了一些資料之後發現,喔,這是不可行的啦。
scss 都叫 "預"處理器了,所以關於 scss 的資訊在檔案編譯成 css 的時候都會消失,也就無法再透過 javascript 去更改了。
結論: scss 沒辦法搭配 javascript 做到這種操作。
但是~~!這樣的效果可以考慮使用 css 的變數來完成。
css 變數常見的寫法之一是把變數宣告放在一個 :root 的偽元素中。
為什麼是 :root 呢?
主要是因為,宣告及使用 CSS 變數和宣告及使用 JS 變數一樣,是有作用範圍 (scope) 的。
若將變數宣告在某個元素的 CSS 內,只有該元素本身以及該元素的子元素、孫元素、子子孫孫們能夠使用該變數。
而 :root 這個虛擬類別 (pseudo-class) 代表 DOM 的根,
也就是 的 CSS Selector,由於它是整顆 DOM 的最高點,因此大家都可以輕易地使用掛在上面的 CSS 變數。
了解以上原理之後,馬上來實作一下。
<style lang="css" scoped>
:root {
--mainColor1: rgb(27, 233, 20);
}
.header {
background: var(--mainColor1);
}
</style>
然後你可能會發現,樣式沒吃到誒!!!
怎麼回事?
測試一下之後,會發現一切問題的癥結好像就是那個 scoped!
我們把 scoped 拿掉看看?好的,這下有樣式了!!
但是,為什麼呢???
先複習一下 scoped 的功能:
When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only.
翻譯成中文大概就是加入 scoped 屬性的 <style> tag 的樣式只會套用於當前套件。
通常會使用 scoped 是為了不汙染全域的樣式。
實測時可以發現,如果加上了 scoped,vue 在渲染之後元素會替其加上 [data-v-1c570aa7] 類似這樣的東西來達成確保樣式唯一的目的。
然而,像這樣的東西,
[data-v-1c570aa7]:root {
--mainColor1: rgb(27, 233, 20);
}
是無法對應到實際的 :root 元素的。
也就會導致沒有樣式效果的結果。
ps. 原文這句的 target 我有點不知道怎麼翻: it will not target actual :root element.
所以講那麼多,其實解決方式也很簡單粗暴,就是拿掉 scoped。
不過要注意也可能因此造成樣式衝突就是了。
參考文章
How to control Sass Variable with javascript
css variable + sass variable = 😍
Day 3 - CSS Variables
vue中scoped的原理及慎用原因
Scoped CSS
CSS variables use in Vue