點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Vue 改變 Local CSS Variable

Sam Xiao's Avatar 2021-02-05

若有數值在 CSS 重複出現,我們可將其抽成 CSS Variable,將來只需維護一處即可:若能將 JavaScript Variable 與 CSS Variable 綁定,則可使用 JavaScript 動態改變 CSS。

Version

Vue 2.6.11

Background Color

variable000

<div> 的背景色為 紅色

<template>
  <div class="bar"/>
</template>

<style scoped>
.bar {
  height: 30px;
  background-color: #f00;
}
</style>
  • background-color: #f000:設定 <div> 的背景為紅色

Local CSS Variable

local003

<div> 背景一樣是紅色,但改用 local CSS variable。

<template>
  <div class="bar"/>
</template>

<style scoped>
.bar {
  height: 30px;
  --bgColor: #f00;
  background-color: var(--bgColor);
}
</style>
  • -- 設定 bgColor
  • 並以 var() 使用 --bgColor

目前 --bgColor 只是 CSS scope 的 variable,JavaScript 並無法與之連動

Style Binding

local004

<div> 背景一樣是紅色,但改用 Vue 的 style binding。

<template>
  <div :style="cssVars" class="bar"/>
</template>

<script>
let cssVars = function() {
  return { '--bgColor': this.bgColor }
}

export default {
  data: () => ({
    bgColor: '#f00'
  }),
  computed: {
    cssVars
  }
}
</script>

<style scoped>
.bar {
  height: 30px;
  background-color: var(--bgColor);
}
</style>

21 行

.bar {
  height: 30px;
  background-color: var(--bgColor);
}

CSS 只使用了 var(--bgColor),並沒有定義其值為 #f00

此時 WebStorm 會警告找不到 --bgColor,可以不用理會

11 行

data: () => ({
  bgColor: '#f00'
}),

bgColor 在 Vue 內定義其值為 #f00

第 6 行

let cssVars = function() {
  return { '--bgColor': this.bgColor }
}

cssVars computed 內以 bgColor data 值定義 --bgColor

第 2 行

<div :style="cssVars" class="bar"/>

cssVars computed 綁定到 style attribute。

透過 Vue 的 computed 與 style binding,我們可將 value 統一定義在 Vue 的 data 內,並將 JavaScript variable 與 CSS variable 綁定之

local002

Vue 其實是將 computed 綁定到 <div> 的 inline style 底下,由於 bar class 也在 <div> 的 scope,因此可以存取 --bgColor

Change Color

variable001

Vue 綁定 CSS variable 後,最大的價值在於可以使用 JavaScript 改變之。

按下 Change Color 後,<div> 背景色從 紅色 變成 綠色

<template>
  <div>
    <div :style="cssVars" class="bar"/>
    <button @click="onClick">Change Color</button>
  </div>
</template>

<script>
let cssVars = function() {
  return { '--bgColor': this.bgColor }
}

let onClick = function() {
  this.bgColor = '#0f0'
}

export default {
  data: () => ({
    bgColor: '#f00'
  }),
  computed: {
    cssVars
  },
  methods: {
    onClick
  }
}
</script>

<style scoped>
.bar {
  height: 30px;
  background-color: var(--bgColor);
}
</style>

13 行

let onClick = function() {
  this.bgColor = '#0f0'
}

在 Vue 的 bgColor data 改成 綠色,則 CSS variable 也會同步改成 綠色

如此就能以 JavaScript 邏輯改變 CSS variable,不再如以往只存在於 CSS scope,而無法與 JavaScript 連動

Conclusion

  • 可將 local CSS variable 之初始值都寫在 Vue 的 data 統一管理,避免初始值因寫在 <style> 內而忘記
  • Vue 2 雖然能將 local CSS variable 與 Vue 綁定,但步驟稍嫌繁瑣,Vue 3 則提供了更精簡方式

Reference

Rainforest, 當 Vue 遇上 CSS Variables