前端主题切换
方案1:css變量+類名切換
提前將樣式文件載入,切換時將指定的根元素類名更換。不過這里相對靈活的是,默認在根作用域下定義好CSS變量,只需要在不同的主題下更改CSS變量對應的取值即可。
順帶提一下,在Vue3官網還使用了color-scheme: dark;將系統的滾動條設置為了黑色模式,使樣式更加統一。
實現方案如下:
/* 定義根作用域下的變量 */ :root {--theme-color: #333;--theme-background: #eee; } /* 更改dark類名下變量的取值 */ .dark{--theme-color: #eee;--theme-background: #333; } /* 更改pink類名下變量的取值 */ .pink{--theme-color: #fff;--theme-background: pink; }.box {transition: all .2s;width: 100px;height: 100px;border: 1px solid #000;/* 使用變量 */color: var(--theme-color);background: var(--theme-background); }表現效果如下:
優點:
不用重新加載樣式文件,在樣式切換時不會有卡頓
在需要切換主題的地方利用var()綁定變量即可,不存在優先級問題
新增或修改主題方便靈活,僅需新增或修改CSS變量即可,在var()綁定樣式變量的地方就會自動更換
缺點:
IE兼容性(忽略不計)
首屏加載時會犧牲一些時間加載樣式資源
方案2:SCSS + mixin + 類名切換
主要是運用SCSS的混合+CSS類名切換,其原理主要是將使用到mixin混合的地方編譯為固定的CSS以后,再通過類名切換去做樣式的覆蓋,實現方案如下:
定義SCSS變量:
/* 字體定義規范 */ $font_samll:12Px; $font_medium_s:14Px; $font_medium:16Px; $font_large:18Px;/* 背景顏色規范(主要) */ $background-color-theme: #d43c33;//背景主題顏色默認(網易紅) $background-color-theme1: #42b983;//背景主題顏色1(QQ綠) $background-color-theme2: #333;//背景主題顏色2(夜間模式)/* 背景顏色規范(次要) */ $background-color-sub-theme: #f5f5f5;//背景主題顏色默認(網易紅) $background-color-sub-theme1: #f5f5f5;//背景主題顏色1(QQ綠) $background-color-sub-theme2: #444;//背景主題顏色2(夜間模式)/* 字體顏色規范(默認) */ $font-color-theme : #666;//字體主題顏色默認(網易) $font-color-theme1 : #666;//字體主題顏色1(QQ) $font-color-theme2 : #ddd;//字體主題顏色2(夜間模式)/* 字體顏色規范(激活) */ $font-active-color-theme : #d43c33;//字體主題顏色默認(網易紅) $font-active-color-theme1 : #42b983;//字體主題顏色1(QQ綠) $font-active-color-theme2 : #ffcc33;//字體主題顏色2(夜間模式)/* 邊框顏色 */ $border-color-theme : #d43c33;//邊框主題顏色默認(網易) $border-color-theme1 : #42b983;//邊框主題顏色1(QQ) $border-color-theme2 : #ffcc33;//邊框主題顏色2(夜間模式)/* 字體圖標顏色 */ $icon-color-theme : #ffffff;//邊框主題顏色默認(網易) $icon-color-theme1 : #ffffff;//邊框主題顏色1(QQ) $icon-color-theme2 : #ffcc2f;//邊框主題顏色2(夜間模式) $icon-theme : #d43c33;//邊框主題顏色默認(網易) $icon-theme1 : #42b983;//邊框主題顏色1(QQ) $icon-theme2 : #ffcc2f;//邊框主題顏色2(夜間模式)定義混合mixin:
@import "./variable.scss";@mixin bg_color(){background: $background-color-theme;[data-theme=theme1] & {background: $background-color-theme1;}[data-theme=theme2] & {background: $background-color-theme2;} } @mixin bg_sub_color(){background: $background-color-sub-theme;[data-theme=theme1] & {background: $background-color-sub-theme1;}[data-theme=theme2] & {background: $background-color-sub-theme2;} }@mixin font_color(){color: $font-color-theme;[data-theme=theme1] & {color: $font-color-theme1;}[data-theme=theme2] & {color: $font-color-theme2;} } @mixin font_active_color(){color: $font-active-color-theme;[data-theme=theme1] & {color: $font-active-color-theme1;}[data-theme=theme2] & {color: $font-active-color-theme2;} }@mixin icon_color(){color: $icon-color-theme;[data-theme=theme1] & {color: $icon-color-theme1;}[data-theme=theme2] & {color: $icon-color-theme2;} }@mixin border_color(){border-color: $border-color-theme;[data-theme=theme1] & {border-color: $border-color-theme1;}[data-theme=theme2] & {border-color: $border-color-theme2;} } <template><div class="header" @click="changeTheme"><div class="header-left"><slot name="left">左邊</slot></div><slot name="center" class="">中間</slot><div class="header-right"><slot name="right">右邊</slot></div></div> </template><script>export default {name: 'Header',methods: {changeTheme () {document.documentElement.setAttribute('data-theme', 'theme1')}}} </script><style scoped lang="scss"> @import "../assets/css/variable"; @import "../assets/css/mixin"; .header{width: 100%;height: 100px;font-size: $font_medium;@include bg_color(); } </style>表現效果如下:
方案6:CSS變量+動態setProperty
此方案較于前幾種會更加靈活,不過視情況而定,這個方案適用于由用戶根據顏色面板自行設定各種顏色主題,這種是主題顏色不確定的情況,而前幾種方案更適用于定義預設的幾種主題。
方案參考:vue-element-plus-admin
主要實現思路如下:
只需在全局中設置好預設的全局CSS變量樣式,無需單獨為每一個主題類名下重新設定CSS變量值,因為主題是由用戶動態決定。
定義一個工具類方法,用于修改指定的CSS變量值,調用的是CSSStyleDeclaration.setProperty
export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {dom.style.setProperty(prop, val) }在樣式發生改變時調用此方法即可
setCssVar('--theme-color', color)表現效果如下:
vue-element-plus-admin主題切換源碼:
這里還用了vueuse的useCssVar不過效果和Vue3中使用v-bind綁定動態樣式是差不多的,底層都是調用的CSSStyleDeclaration.setProperty這個api,這里就不多贅述vueuse中的用法。
優點:
不用重新加載樣式文件,在樣式切換時不會有卡頓
仔細琢磨可以發現其原理跟方案4利用Vue3的新特性v-bind是一致的,只不過此方案只在:root上動態更改CSS變量而Vue3中會將CSS變量綁定到任何依賴該變量的節點上。
需要切換主題的地方只用在:root上動態更改CSS變量值即可,不存在優先級問題
新增或修改主題方便靈活
缺點:
IE兼容性(忽略不計)
首屏加載時會犧牲一些時間加載樣式資源(相對于前幾種預設好的主題,這種方式的樣式定義在首屏加載基本可以忽略不計)
作者:四相前端團隊
鏈接:https://juejin.cn/post/7134594122391748615
來源:稀土掘金
總結
- 上一篇: 汽车IVI中控开发入门及进阶(三):概述
- 下一篇: 2017年html5行业报告,云适配发布