当前位置: 首页 > Web前端 > HTML

Sass应用程序中实现主题切换

时间:2023-03-28 12:32:41 HTML

Sass应用程序中实现主题切换背景实现主题切换有几种不同的解决方案,例如使用CSS变量,使用JavaScript动态加载相应的主题样式文件等。本文主要讲一下如何使用Sass实现主题切换。前置知识使用变量mixinmap了解Sass的基础本质上Sass是作为CSS预处理器使用的,需要编译成CSS才能被浏览器识别和解析。所以不能直接在浏览器中使用Sass来实现类似于CSS变量的动态切换。本质上,如果项目中有多个主题,需要提前定义好几个主题样式,然后全部导入。思路首先,我们需要在应用的顶层元素中添加一个主题标识,用于标识当前的主题,用于后面应用上相应的主题样式。标识符可以是数据属性,也可以是类,也可以是id,这里用的是数据属性。

然后,每次切换主题时,通过更新标志,页面将应用预定义的style文件对应的主题风格。.app{&[data-theme='light']{颜色:#333;}&[data-theme='dark']{颜色:#fff;}}基于主题切换的本质和思想来实现基础版,我们可以硬编码实现一个简单的主题切换。Hello,World当前主题:Bright颜色

lightdark
首先给应用添加一个主题标识,这里我通过给body元素添加一个数据属性data-theme来表示当前的主题。默认是light
然后提前定义好所有的主题样式://Allthemestyles$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{//默认主题风格(浅色主题)background-color:$bg-color-light;//深色主题[data-theme='dark']&{background-color:$bg-color-dark;}}.title{颜色:$title-color-light;[data-theme='dark']&{color:$title-color-dark;}}.subtitle{颜色:$subtitle-color-light;[data-theme='dark']&{color:$subtitle-color-dark;}}最后,当我们点击不同的主题按钮时,body上的主题标识data-theme会被更新,这样样式文件中对应的主题样式就会被应用。完整的代码和实现效果可以参考Codepen:SASSforthemeskinning/themeswitching-basicversionbyzhouqichao(@Tom_chao)不过实现起来有点粗糙,还有几个小问题:在每个CSS选择器中,需要应用主题样式,写对应主题需要的样式比较麻烦。如果有多个主题,代码量会大大增加,而且很多都是重复的“模板代码”。针对这些问题,我们可以利用Sass的一些特性来实现高级版的主题切换。进阶版首先,解决基础版暴露的问题。我们需要对Sass变量做一个小的调整。这里我们将主题风格封装成地图格式,地图中的每个元素对应不同主题下的风格。//所有主题样式$bg-color:(//lightcolorlight:#fff,//darkcolordark:#091a28);$标题颜色:(浅色:#363636,深色:#ffffff);$字幕颜色:(浅色:#4a4a4a,深色:青色);为了解决模板代码重复、代码繁琐的问题,Sass中有一个featuremixin,直接使用就可以了。接下来,我们需要封装一个mixin,专门解决基础版本1——手写代码繁琐的问题。这里使用了Sass中的插值表达式#{}和map-get方法。#{}类似于JavaScript中的计算属性,可以动态设置属性名。map-get方法用于从地图中获取某个属性对应的值。.@mixinthemify($key,$valueMap){//默认主题#{$key}:map-get($valueMap,'light');//深色主题[data-theme='dark']&{#{$key}:map-get($valueMap,'dark');}}themify主要封装了默认的主题样式light和dark主题样式,所以我们只需要在选择器中包含这些样式即可。.app{@includethemify('background-color',$bg-color);}.title{@includethemify('color',$title-color);}.subtitle{@includethemify('color',$subtitle-color);}现在代码是不是简洁多了?忘记手工编写那些繁琐的模板代码吧!对于“多主题模板代码会多”的问题,很容易解决。只需简单修改mixin,添加相应的主题样式即可。@mixinthemify($key,$valueMap){//浅色主题#{$key}:map-get($valueMap,'light');//深色主题[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');}}当然我们也可以优化mixin,主题可以封装成列表格式,然后通过遍历主题来简化mixin:@mixinthemify($key,$valueMap){//themelist$themes:光线暗;@each$themein$themes{[data-theme=#{$theme}]&{#{$key}:map-get($valueMap,$theme);}}}这看起来干净多了。完整代码和实现效果可以参考Codepen:SASS实现主题换肤/主题切换-高级版byzhouqichao(@Tom_chao),为实现主题切换提供了很多便利。当然,在Sass中实现主题切换还有很多可以优化的地方。这里有两个常见的:如果有多个主题样式需要应用,那么必须每个都写一次@include,感觉有点麻烦。你能只写一次@include吗?.app{@includethemify('background-color',$bg-color);@includethemify('color',$text-color);//...}//我希望我只能写一次@include.app{@includethemify(('background-color':$bg-color,'color':$text-color));}如果还是需要用!important来覆盖一些因为weight问题不能应用的样式(比如使用外部UI库,!important在外部UI库中使用,需要重写这个样式),如何解决?//这里有一个思路,可以在themify($key,$valueMap:null,$important:false)中加一个参数$important@mixin{//xxx}