PM说要实现一个一键设置主题的功能,做为技术,你能想到的实现方式有哪些呢?
相信你们对网页的主题样式功能确定不陌生。对于一些站点,在基础样式上,开发者还会为用户提供多种主题样式以供选择。css
下面就是一个主题样式功能:用户能够在右侧选择本身喜欢的主题色,从而获得一个“个性”的页面。html
还有时候,咱们开发了一个系统用来售卖,采购咱们系统的客户可能有多个。也许其中一个客户很喜欢咱们当前的深色色系主题,可是另外一个系统的采购方但愿咱们能为它们定制一套新的样式。他们但愿买来的系统能贴合它们本身的品牌调性,变为浅色的。这其实也是一种主题样式的需求。浏览器
在上面的讨论里,除了“主题”外,咱们又引出了一个概念——个性化。常常,咱们说到主题时,还会有一种说法叫作:个性化主题。这二者在英文中分别有两个对应的词: Theming 与 Customisation。缓存
当咱们说主题(Theming)与个性化定制(Customisation)的时候,不少时候其实并无区分二者。但实际上,二者仍是有一些微妙的区别的。工具
咱们说的主题(Theming)与个性化定制(Customisation)的时候,仍是有一些微妙的区别的。字体
主要表如今:网站
例如,咱们常见的一些应用会提供夜间主题、阅读模式,这些也算是主题(Theming)的范畴。spa
特色表如今:code
能够看到,“个性化”其实更强调了用户对系统的的影响力。component
不少时候,咱们谈到“主题”与“个性化定制”时,也许并无一个明确的边界。从上面的描述也能够看出,二者彷佛是处于天平的两端,区别主要在于开发者对规则的控制力度以及所能实现的差别化的粒度。
而咱们更多的是在两点之间找到一个平衡点。
咱们已经对主题样式有了初步的了解,若是你也在产品中遇到了主题样式的相关需求,不妨先看看如下几点建议:
Overriding default style with additional CSS.
这应该是实现主题功能的一种最经常使用的手段了。首先,咱们的站点会有一个最初的基础样式(或者叫默认样式);而后经过添加一些后续的额外的CSS来覆盖与从新定义部分样式。
首先,咱们引入基础的样式 components.*
文件
@import "components.tabs"; @import "components.buttons"
其中 components.tabs
文件内容以下
.tab { margin: 0; padding: 0; background-color: gray; }
而后,假设咱们的某个主题的样式文件存放于 theme.*
文件:
对应于 components.tabs
,theme.tabs
文件内容以下
.tab { background-color: red; }
所以,咱们只须要引入主题样式文件便可
@import "components.tabs"; @import "components.buttons" @import "theme.tabs";
这样当前的样式就变为了
.tab { margin: 0; padding: 0; /* background-color: gray; */ background-color: red; }
Styling a UI based on a state or condition.
该方式能够实现基于条件选择不一样的主题皮肤,并容许用户在客户端随时切换主题。很是适合须要客户端样式切换功能,或者须要对站点某一部分(区域)进行独立样式设置的场景。
仍是相似上一节中 Tab 的这个例子,咱们能够将 Tab 部分的 (S)CSS 改成以下形式:
.tab { background-color: gray; .t-red & { background-color: red; } .t-blue & { background-color: blue; } }
这里咱们把.t-red
与.t-blue
称为 Tab 元素的上下文环境(context)。Tab 元素会根据 context 的不一样展现出不一样的样式。
最后咱们给body
元素加上这个开关
<body class="t-red"> <ul class="tabs">...</ul> </body>
此时 Tab 的颜色为红色。
当咱们将t-red
改成t-blue
时,Tab 就变为了蓝色主题。
进一步的,咱们能够建立一些 (S)CSS 的 util class(工具类)来专门控制一些 CSS 属性,帮助咱们更好地控制主题。例如咱们使用以下的.u-color-current
类来控制不一样主题下的字体颜色
.u-color-current { .t-red & { color: red; } .t-blue & { color: blue; } }
这样,当咱们在不一样主题上下文环境下使用.u-color-current
时,就能够控制元素展现出不一样主题的字体颜色
<body class="t-red"> <h1 class="page-title u-color-current">...</h1> </body>
上面这段代码会控制<h1>
元素字体颜色为红色主题时的颜色。
Invoking a theme based on settings.
这种方式实际上是在开发侧来实现主题样式的区分与切换的。基于不一样的配置,配合一些开发的自动化工具,咱们能够在开发时期根据配置文件,编译生成不一样主题的 CSS 文件。
它通常会结合使用一些 CSS 预处理器,能够对不一样的 UI 元素进行主题分离,而且向客户端直接提供主题样式下最终的 CSS。
咱们仍是以 Sass 为例:
首先会有一份 Sass 的配置文件,例如settings.config.scss
,在这份配置中定义当前的主题值以及一些其余变量
$theme: red;
而后对于一个 Tab 组件,咱们这么来写它的 Sass 文件
.tab { margin: 0; padding: 0; @if ($theme == red) { background-color: red; } @else { background-color: gray; } }
这时,咱们在其以前引入相应的配置文件后
@import "settings.config"; @import "components.tabs";
Tab 组件就会呈现出红色主题。
固然,咱们也能够把咱们的settings.config.scss
作的更健壮与易扩展一些
$config: ( theme: red, env: dev, ) // 从$config中获取相应的配置变量 @function config($key) { @return map-get($config, $key); }
与以前相比,这时候使用起来只须要进行一些小的修改,将直接使用theme
变量改成调用config
方法
.tab { margin: 0; padding: 0; @if (config(theme) == red) { background-color: red; } @else { background-color: gray; } }
settings.config.scss
文件)Holding entire themes in a palette file.
这种方式有些相似于咱们绘图时,预设了一个调色板(palette),而后使用的颜色都从其中取出同样。
在实现主题功能时,咱们也会有一个相似的“调色板”,其中定义了主题所须要的各类属性值,以后再将这些信息注入到项目中。
当你常常须要为客户端提供彻底的定制化主题,而且常常但愿更新或添加主题时,这种模式会是一个不错的选择。
在方式三中,咱们在一个独立的配置文件中设置了一些“环境”变量,来标示当前所处的主题。而在方式四中,咱们会更进一步,抽取出一个专门的 palette 文件,用于存放不一样主题的变量信息。
例如,如今咱们有一个settings.palette.red.scss
文件
$color: red; $color-tabs-background: $color-red;
而后咱们的components.tabs.scss
文件内容以下
.tabs { margin: 0; padding: 0; backgroung-color: $color-tabs-background; }
这时候,咱们只须要引入这两个文件便可
@import "settings.palette.red"; @import "components.tabs";
能够看到,components.tabs.scss
中并无关于主题的逻辑判断,咱们只须要专一于编辑样式,剩下就是选择所需的主题调色板(palette)便可。
Letting users style their own UIs.
这种模式通常会提供一个个性化配置与管理界面,让用户能本身定义页面的展现样式。
“用户定制化”在社交媒体产品、SaaS 平台或者是 Brandable Software 中最为常见。
要实现定制化,能够结合方式二中提到的 util class。
首先,页面中支持自定义的元素会被预先添加 util class,例如 Tab 元素中的u-user-color-background
<ul class="tabs u-user-color-background">...</ul>
此时,u-user-color-background
还并未定义任何样式。而当用户输入了一个背景色时,咱们会建立一个<style>
标签,并将 hex 值注入其中
<style id="my-custom"> .u-user-color-background { background-color: #00ffff; } </style>
这时用户就获得了一个红色的 Tab。
Twitter 就是使用这种方式来实现用户定制化的界面样式的:
最后来聊聊方案的选择。
在第二部分咱们已经了解了五种实现方式(或者说4½种方法,由于第五种其实更偏个性化定制一些),那么面对产品需求,咱们应该如何选择呢?
这里有一个不是很是严谨的方式能够参考。你能够经过尝试问本身下面这几个问题来作出决定:
用户:选择【方式五】User Customisation
是:选择【方式二】Stateful Theming 或【方式五】User Customisation
是:选择【方式二】Stateful Theming
是:选择【方式二】Stateful Theming
是:选择【方式三】Config Theming
是:选择【方式一】Theme Layer 或【方式四】Theme Palettes