<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 5764字,需瀏覽 12分鐘

           ·

          2022-06-24 18:03

          作者:瑪爾斯通

          來(lái)源:SegmentFault  思否社區(qū) 



          背景



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

          前置知識(shí)



          了解Sass的基本使用

          • variable
          • mixin
          • map


          本質(zhì)



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


          思路



          首先,我們需要給應(yīng)用的頂層元素添加一個(gè)主題標(biāo)識(shí),用于標(biāo)識(shí)當(dāng)前的主題,用于之后應(yīng)用上對(duì)應(yīng)的主題樣式。該標(biāo)識(shí)可以是數(shù)據(jù)屬性,也可以是類,也可以是id,這里采用數(shù)據(jù)屬性。

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

          然后,每次切換主題時(shí),通過(guò)更新該標(biāo)識(shí),頁(yè)面就會(huì)應(yīng)用樣式文件中提前定義好的對(duì)應(yīng)的主題樣式。

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

          實(shí)現(xiàn)



          基礎(chǔ)版


          基于主題切換的本質(zhì)和思路,我們可以通過(guò)硬編碼,實(shí)現(xiàn)一個(gè)簡(jiǎ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)用添加一個(gè)主題標(biāo)識(shí),這里我通過(guò)給body元素添加一個(gè)數(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主題
            [theme='dark'] & {
              background-color: $bg-color-dark;
            }
          }

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

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

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

          完整代碼和實(shí)現(xiàn)效果可以參考Codepen:
          https://codepen.io/Tom_chao/pen/ExwbmaP

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

          1. 每個(gè)需要應(yīng)用主題樣式的CSS選擇器中,都要寫(xiě)一遍對(duì)應(yīng)主題需要的樣式,比較繁瑣



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



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

          進(jìn)階版


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

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

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

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

          針對(duì)重復(fù)的模版代碼和代碼繁瑣的問(wèn)題,Sass中有個(gè)特性mixin,正好可以利用上。

          接下來(lái),我們要封裝一個(gè)mixin,專門(mén)解決基礎(chǔ)版1-手寫(xiě)代碼的繁瑣的問(wèn)題。

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

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

          themify主要封裝了默認(rèn)主題樣式light,和dark主題樣式,這樣我們?cè)谶x擇器里,只需要include這些樣式即可。

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

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

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

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

          針對(duì)“多主題模版代碼會(huì)更多”的問(wèn)題,解決起來(lái)也就很容易了。只需要簡(jiǎn)單修改下該mixin,添加上對(duì)應(yīng)的主題樣式即可。

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

          當(dāng)然,我們還可以對(duì)mixin做一下優(yōu)化,可以將主題封裝成list格式,然后通過(guò)遍歷主題,簡(jiǎn)化mixin:

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

          這樣看起來(lái)就清爽多了。

          完整代碼和實(shí)現(xiàn)效果可以參考Codepen:
          https://codepen.io/Tom_chao/pen/YzrEVZY

          總結(jié)



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


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

          • 如果有多條主題樣式需要應(yīng)用,每一條都要寫(xiě)一遍@include,感覺(jué)有點(diǎn)麻煩,能不能只寫(xiě)一遍@include?

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

          // 希望可以只寫(xiě)一遍@include
          .app {
            @include themify(
              (
              'background-color'$bg-color,
              'color'$text-color
              )
            );
          }

          • 如果還需要使用!important去覆蓋一些因?yàn)闄?quán)重問(wèn)題無(wú)法應(yīng)用的樣式(比如使用了外部UI庫(kù),外部UI庫(kù)中使用了!important,需要覆蓋該樣式),怎么解決?

          // 這里提供一個(gè)思路,可以添加一個(gè)參數(shù)$important
          @mixin themify($key$valueMap: null, $importantfalse) {
              // xxx
          }



          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開(kāi)更多互動(dòng)和交流,掃描下方”二維碼“或在“公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 123
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人妻性爱在线 | 无码视频免费在线播放 | 欧美操操图片 | 五月天操逼图 | 黄色片视频免费 |