四时宝库

程序员的知识宝库

用SCSS实现多主题、一键换肤、跟随系统切换主题

前言

在项目开发中,一般情况下,我们都不希望我们的站点是一成不变的,经常会有多主题的需求,如常见的浅色和深色主题

现在,较新版本的操作系统基本都可以支持深色模式了,很多应用、网页为了提高用户体验,也会有适配系统主题的浅色深色主题,当系统处于深色模式,打开应用、网页,显示的也为对应的深色模式主题,而不是说依旧为浅色主题,会给用户一种很亮的感觉,刺激用户感官

具体实现

根据不同的需求,我们可以实现多套主题,以下仅从浅色和深色主题举例介绍

原理分析

主题,即UI风格,如背景色、文字颜色、文字大小等

在前端中,每一套主题其实就是对应着一套CSS样式表,多主题的切换,其实就是样式表的切换

主题实现

实现多主题的方式有很多种,常见的就是通过变量,不同主题对应一套不同的变量值表(变量名一致),在编写CSS时,我们不使用具体的值,而是使用变量,在切换主题时,就是切换不同变量值表,对应的CSS样式就会对应呈现出来,能够较好地实现多主题,也不需要多复杂的操作

主题切换

主题切换的方式可以有很多种

如果是有多个主题,由用户选择控制主题变化,可以用JS配合CSS类或元素自定义属性实现

  • 当用户选择切换主题时,比如切换到dark主题,那么就给htmlbody添加一个名为dark的类;或者添加一个自定义属性(如:data-theme),设置其值为dark,然后在CSS内可针对这些约定好的特性设置对应的样式、变量值等

如果只有浅色和深色主题,并且希望根据用户系统主题进行自动切换,可以使用@media的一个特性prefers-color-scheme,其可以检测用户系统当前的主题色

  • prefers-color-scheme,其可以检测用户系统当前的主题色,其有三个值
    • no-preference — 表示获取不到,可能用户浏览器不支持该属性或功能被禁止
    • light — 表示系统当前为浅色主题
    • dark — 表示系统当前为深色主题
    • 其大致使用方法如下:
    • 以上示例中,当系统主题为深色时,body背景色呈现为#000,反之则呈现为#fff

举个栗子

以下均从浅色深色两个主题进行讲解,更多主题可自行扩展

CSS实现方式

首先,我们定义套变量表

  • 第一种采用自定义属性进行区分,切换主题时,只需将html元素的data-theme值改为对应主题值即可
  • 第二种采用@media进行媒体查询判断,当系统为浅色主题,则会自动渲染相应主题(无效可能为浏览器问题,可查看浏览器主题是否设置跟随系统)

当然主题不一定只是变量的变化,也可以是不同样式、布局等,同样的只需用类似上面变量定义的方法,用对应的方法进行约束,如下:

如上,简单展示了不同主题,不同布局的情况,用相同的类达到目的

  • 用自定义属性的方式,那么选择器均需通过html[data-theme="value"]进行约束
  • @media的方式,则需将选择器样式写于@media范围内

SCSS实现方式

实现纯CSS的方式可以达到想要效果,但过程会稍显繁复,且大量使用CSS变量可能有一定的性能问题(虽然理论上并不会有明显问题)

我们可以用SCSS的能力简化我们的主题样式编写,同时通过SCSS变量最终编译出的CSS使用的是固定静态值

首先,为了结构比较清晰,可以把主题变量单纯定义在一个文件内,方便扩展,如下:

接着,定义一些mixinfunction,用于方便主题开发,如下

使用如下,只需在需编写主题样式的样式表内引入该文件使用即可

生成CSS如下:

使用这种方式,在项目的任何位置,如果需要编写主题相关样式,只需引入上侧index.scss文件即可,参考上侧app.scss使用即可

如果你是用框架开发,如Vue,可以进行一些配置,使其注入到全局,这样就不用使用时都要引入index.scss,如下

在配置文件vite.config.ts内配置

通过这种配置,在项目中编写主题样式时,直接使用useTheme这些方法即可

通过SCSS可以大大地节省我们编写复杂样式的时间,还可以进行一些复杂运算,如根据主题色计算出其它搭配色等操作,有兴趣的可自行深入


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接