Sass應(yīng)用之實(shí)現(xiàn)主題切換

背景

實(shí)現(xiàn)主題切換有幾種不同的方案载荔,比如使用CSS變量,使用JavaScript動態(tài)加載對應(yīng)的主題樣式文件等翘狱。本文主要講的是如何使用Sass實(shí)現(xiàn)主題切換鼎兽。

前置知識

了解Sass的基本使用

  • variable
  • mixin
  • map

本質(zhì)

Sass作為CSS預(yù)處理器,需要編譯成CSS后漓糙,才能被瀏覽器識別和解析铣缠。因此無法在瀏覽器中直接使用Sass實(shí)現(xiàn)類似CSS變量那種動態(tài)切換。本質(zhì)上來說昆禽,項(xiàng)目中有幾個主題就要提前定義好幾份主題樣式并全部引入蝗蛙。

思路

首先,我們需要給應(yīng)用的頂層元素添加一個主題標(biāo)識醉鳖,用于標(biāo)識當(dāng)前的主題捡硅,用于之后應(yīng)用上對應(yīng)的主題樣式。該標(biāo)識可以是數(shù)據(jù)屬性辐棒,也可以是類病曾,也可以是id牍蜂,這里采用數(shù)據(jù)屬性。

<html>
  <div class="app" data-theme="light"></div>
</html>

然后泰涂,每次切換主題時(shí)鲫竞,通過更新該標(biāo)識,頁面就會應(yīng)用樣式文件中提前定義好的對應(yīng)的主題樣式逼蒙。

.app {
  &[data-theme='light'] {
    color: #333;
  }
  
  &[data-theme='dark'] {
    color: #fff;
  }
}

實(shí)現(xiàn)

基礎(chǔ)版

基于主題切換的本質(zhì)和思路从绘,我們可以通過硬編碼,實(shí)現(xiàn)一個簡單的主題切換是牢。

<div id="app" class="app">
  <h1 class="title">Hello, World</h1>
  <p class="subtitle">當(dāng)前主題:<span id="theme-current">亮色</span></p>
  <button class="theme-switch light" data-theme="light">亮色</button>
  <button class="theme-switch dark" data-theme="dark">暗色</button>
</div>

首先給應(yīng)用添加一個主題標(biāo)識僵井,這里我通過給body元素添加一個數(shù)據(jù)屬性data-theme表示當(dāng)前的主題。默認(rèn)為light

<body data-theme="light">
  <div class="app"></div>
</body>

然后提前定義好所有主題樣式:

// 所有主題樣式
$bg-color-light: #ffffff;
$bg-color-dark: #091a28;
$title-color-light: #363636;
$title-color-dark: #ffffff;
$subtitle-color-light: #4a4a4a;
$subtitle-color-dark: cyan;

.app {
  // 默認(rèn)主題樣式(light主題)
  background-color: $bg-color-light;
  
  // dark主題
  [data-theme='dark'] & {
    background-color: $bg-color-dark;
  }
}

.title {
  color: $title-color-light;
  
  [data-theme='dark'] & {
    color: $title-color-dark;
  }
}

.subtitle {
  color: $subtitle-color-light;
  
  [data-theme='dark'] & {
    color: $subtitle-color-dark;
  }
}

最后驳棱,當(dāng)我們點(diǎn)擊不同主題按鈕時(shí)批什,就會更新body上的主題標(biāo)識data-theme,這樣社搅,樣式文件中對應(yīng)的主題樣式就會被應(yīng)用上了驻债。

完整代碼和實(shí)現(xiàn)效果可以參考Codepen:
CodePen: SASS實(shí)現(xiàn)主題換膚/主題切換-基礎(chǔ)版

不過該實(shí)現(xiàn)有點(diǎn)粗糙,存在幾個小問題:

  1. 每個需要應(yīng)用主題樣式的CSS選擇器中形葬,都要寫一遍對應(yīng)主題需要的樣式合呐,比較繁瑣


  2. 如果有多個主題,代碼量會極具增加笙以,并且很多都是重復(fù)的“模板代碼”


針對這些問題淌实,我們可以利用Sass的一些特性實(shí)現(xiàn)一個進(jìn)階版的主題切換。

進(jìn)階版

首先猖腕,針對基礎(chǔ)版暴露出的問題拆祈。我們需要對Sass變量做一點(diǎn)小小的調(diào)整。這里我們將主題樣式封裝成了map格式谈息,map中每一個元素都對應(yīng)著不同主題下的樣式缘屹。

// 所有主題樣式
$bg-color: (
  // 亮色
  light: #fff,
  // 暗色
  dark: #091a28
);

$title-color: (
  light: #363636,
  dark: #ffffff
);

$subtitle-color: (
  light: #4a4a4a,
  dark: cyan
);

針對重復(fù)的模版代碼和代碼繁瑣的問題,Sass中有個特性mixin侠仇,正好可以利用上轻姿。

接下來,我們要封裝一個mixin逻炊,專門解決基礎(chǔ)版1-手寫代碼的繁瑣的問題互亮。

這里使用了Sass中的插值表達(dá)#{}map-get方法,#{}類似于JavaScript中的計(jì)算屬性余素,可以動態(tài)設(shè)置屬性名豹休,map-get方法用于從map中獲取某一個屬性對應(yīng)的值吕世。

@mixin themify($key, $valueMap) {
  // 默認(rèn)主題
  #{$key}: map-get($valueMap, 'light');
    
  // dark主題
  [data-theme='dark'] & {
    #{$key}: map-get($valueMap, 'dark');
  }
}

themify主要封裝了默認(rèn)主題樣式light劫扒,和dark主題樣式,這樣我們在選擇器里,只需要include這些樣式即可味廊。

.app {
  @include themify('background-color', $bg-color);
}

.title {
  @include themify('color', $title-color);
}

.subtitle {
  @include themify('color', $subtitle-color);
}

現(xiàn)在看這些代碼是不是簡潔多了榴都?省去了自己手寫那些繁瑣的模板代碼扳抽!

針對“多主題模版代碼會更多”的問題译打,解決起來也就很容易了。只需要簡單修改下該mixin留美,添加上對應(yīng)的主題樣式即可彰檬。

@mixin themify($key, $valueMap) {
  // light主題
  #{$key}: map-get($valueMap, 'light');
    
  // dark主題
  [data-theme='dark'] & {
    #{$key}: map-get($valueMap, 'dark');
  }
  
  // dark1主題
  [data-theme='dark1'] & {
    #{$key}: map-get($valueMap, 'dark1');
  }
  
  // dark2主題
  [data-theme='dark2'] & {
    #{$key}: map-get($valueMap, 'dark2');
  }
}

當(dāng)然,我們還可以對mixin做一下優(yōu)化谎砾,可以將主題封裝成list格式逢倍,然后通過遍歷主題,簡化mixin:

@mixin themify($key, $valueMap) {
  // theme list
  $themes: light, dark;
  
  @each $theme in $themes {
    [data-theme=#{$theme}] & {
      #{$key}: map-get($valueMap, $theme);
    }
  }
}

這樣看起來就清爽多了景图。
完整代碼和實(shí)現(xiàn)效果可以參考Codepen:
CodePen: SASS實(shí)現(xiàn)主題換膚/主題切換-進(jìn)階版

總結(jié)

Sass作為一款流行的CSS預(yù)處理器较雕,提供了插值表達(dá)#{}map類型等特性,在實(shí)現(xiàn)主題切換方面提供了不少便利症歇。

當(dāng)然郎笆,Sass實(shí)現(xiàn)主題切換還有很多可以優(yōu)化的點(diǎn)谭梗。這里隨便列兩條常見的:

  1. 如果有多條主題樣式需要應(yīng)用忘晤,每一條都要寫一遍@include,感覺有點(diǎn)麻煩激捏,能不能只寫一遍@include设塔?

    .app {
      @include themify('background-color', $bg-color);
      @include themify('color', $text-color);
      // ...
    }
    
    // 希望可以只寫一遍@include
    .app {
      @include themify(
        (
        'background-color': $bg-color,
        'color': $text-color
        )
      );
    }
    
  2. 如果還需要使用!important去覆蓋一些因?yàn)闄?quán)重問題無法應(yīng)用的樣式(比如使用了外部UI庫,外部UI庫中使用了!important远舅,需要覆蓋該樣式)闰蛔,怎么解決?

    // 這里提供一個思路图柏,可以添加一個參數(shù)$important
    @mixin themify($key, $valueMap: null, $important: false) {
     // xxx
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末序六,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蚤吹,更是在濱河造成了極大的恐慌例诀,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件裁着,死亡現(xiàn)場離奇詭異繁涂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)二驰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門扔罪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人桶雀,你說我怎么就攤上這事矿酵』8矗” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵全肮,是天一觀的道長盅抚。 經(jīng)常有香客問我,道長倔矾,這世上最難降的妖魔是什么妄均? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮哪自,結(jié)果婚禮上丰包,老公的妹妹穿的比我還像新娘。我一直安慰自己壤巷,他們只是感情好邑彪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胧华,像睡著了一般寄症。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上矩动,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天有巧,我揣著相機(jī)與錄音,去河邊找鬼悲没。 笑死篮迎,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的示姿。 我是一名探鬼主播甜橱,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼栈戳!你這毒婦竟也來了岂傲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤子檀,失蹤者是張志新(化名)和其女友劉穎镊掖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體命锄,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堰乔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了脐恩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镐侯。...
    茶點(diǎn)故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苟翻,到底是詐尸還是另有隱情韵卤,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布崇猫,位于F島的核電站沈条,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诅炉。R本人自食惡果不足惜蜡歹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涕烧。 院中可真熱鬧月而,春花似錦、人聲如沸议纯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瞻凤。三九已至憨攒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阀参,已是汗流浹背肝集。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留结笨,地道東北人包晰。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像炕吸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子勉痴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容