You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{id: 'all-property',title: '`all` Property',description:
'A property for defining the reset of all properties of an element',specification: 'https://www.w3.org/TR/css-cascade-3/#all-shorthand',stage: 3,caniuse: 'css-all',docs:
{mdn: 'https://developer.mozilla.org/en-US/docs/Web/CSS/all'},example: 'a {\n all: initial;\n}',polyfills: [[Object]]}
This is because less is a large javascript file and compiling less before the user can see the page means a delay for the user. In addition, consider that mobile devices will compile slower.
之前在做网站换肤,所以今天想聊聊网站换肤的实现。网页换肤就是修改颜色值,因此重点就在于怎么来替换。
一般实现
如上图,我们会看到在某些网站的右上角会出现这么几个颜色块,点击不同的颜色块,网站的整体颜色就被替换了。要实现它,我们考虑最简单的方式:
点击不同的按钮切换不同的样式表
,如:可以看出,我们需要为每个颜色块编写样式表,那如果我要实现几百种或者让用户自定义呢,显而易见这种方式十本笨拙,且拓展性并不高,另外,如果考虑加载的成本,那其实这种方式并不可取。
ElementUI
的实现ElementUI
的实现比上面的实现高了好几个level,它能让用户自定义颜色值,而且展示效果也更加优雅。当前我的实现就是基于它的思路来实现。我们来看看他是怎么实现的(这里引用的是官方的实现解释):
style
标签,把生成的样式填进去:https://github.com/ElementUI/theme-preview/blob/master/src/app.vue#L198-L211下面我具体讲下我参考它的原理的实现过程 (我们的css 编写是基于
postcss
来编写的):tint(var(--color-primary), 20%)
,darken(var(--color-primary), 15%)
,shade(var(--color-primary), 5%)
等。这也类似就实现了上面的第一步这里我先把全部css文件中可以通过主题色来计算出其他颜色的颜色值汇总在一起,如下:
这里的
color函数
是后面我们调用了 css-color-function 这个包,其api使然。既然对应关系汇总好了,那我们就来进行颜色值的替换。在一开始进入网页的时候,我就先根据默认的主题色根据
formula.js
中的计算颜色汇总表
生成对应的颜色,以便后面的替换,在这过程中使用了css-color-function 这个包,图1:
图2,黑色字即为颜色正则表达式:
好了,当我们拿到了原始值之后,就可以开始进行替换了,这里的替换源是什么?由于我们的网页是通过如下
内嵌style标签
的,所以替换原就是所有的style标签
,而element
是直接去请求网页打包好的的css文件
:下面是核心代码:
效果如下:
至此,我们的颜色值替换已经完成了。正如官方所说,实现原理十分暴力😂,同时感觉使用源css通过
postcss
编译出来的颜色值不好通过css-color-function
这个包来计算的一模一样,好几次我都是对着rgba
的值一直在调🤣🤣,( 👀难受antd
的实现antd
的样式是基于less
来编写的,所以在做换肤的时候也利用了less
可以直接编译css 变量
的特性,直接上手试下。页面中顶部有三个色块,用于充当颜色选择器,下面是用于测试的div块。下面div的css 如下,这里的
@primary-color
和@bg-color
就是less
变量:当我们点击三个色块的时候,直接去加载
less.js
,具体代码如下(参考antd的实现):然后点击色块进行试验,发现并没有生效,这是why?然后就去看了其文档,原来它会找到所有如下的less 样式标签,并且使用已编译的css同步创建 style 标签。也就是说我们必须吧代码中所有的less 都以下面这种link的方式来引入,这样
less.js
才能在浏览器端实现编译。这里我使用了
create-react-app
,所以直接把less
文件放在了public
目录下,然后在html中直接引入:点击
blue
色块,可以看见color
和background
的值确实变了:并且产生了一个
id=less:color
的style 标签,里面就是编译好的css
样式。紧接着我又试了link两个less 文件,然后点击色块:从上图看出,less.js 会为每个less 文件编译出一个style 标签。
接着去看了
antd
的实现,它会调用 antd-theme-generator 来把所有antd组件
或者文档
的less 文件组合为一个文件,并插入html中,有兴趣的可以去看下 antd-theme-generator 的内部实现,可以让你更加深入的了解 less 的编程式用法。基于
CSS自定义变量
的实现先来说下
css自定义变量
,它让我拥有像less/sass
那种定义变量并使用变量的能力,声明变量的时候,变量名前面要加两根连词线(--
),在使用的时候只需要使用var()
来访问即可,看下效果:如果要局部使用,只需要将变量定义在 元素选择器内部即可。具体使用见使用CSS变量,关于 CSS 变量,你需要了解的一切
使用
css 自定义变量
的好处就是我们可以使用js
来改变这个变量:document.body.style.setProperty('--bg', '#7F583F');
来设置变量document.body.style.getPropertyValue('--bg');
来获取变量document.body.style.removeProperty('--bg');
来删除变量有了如上的准备,我们基于
css 变量
来实现的换肤就有思路了:将css 中与换肤有关的颜色值提取出来放在:root{}
中,然后在页面上使用setProperty
来动态改变这些变量值即可。上面说到,我们使用的是
postcss
,postcss 会将css自定义变量直接编译为确定值
,而不是保留
。这时就需要postcss 插件
来为我们保留这些自定义变量,使用 postcss-custom-properties,并且设置preserve=true
后,postcss就会为我们保留了,效果如下:这时候就可以在换肤颜色选择之后调用
document.body.style.setProperty
来实现换肤了。不过这里只是替换一个变量,如果需要根据主颜色来计算出其他颜色从而赋值给其他变量就可能需要调用
css-color-function
这样的颜色计算包来进行计算了。其postcss的插件配置如下(如需其他功能可自行添加插件):
聊下 precss 和 postcss-preset-env
它们相当于
babel
的preset
。precss
其包含的插件如下:使用如下配置也能达到相同的效果,precss 的选项是透传给上面各个插件的,由于
postcss-custom-properties
插件位于postcss-preset-env
中,所以只要按postcss-preset-env
的配置来即可:postcss-preset-env
包含了更多的插件。这了主要了解下其stage
选项,因为当我设置了stage=2
时(precss
中默认postcss-preset-env
的stage= 0
),我的字体图标
竟然没了:这就很神奇,由于没有往
代码的编写
上想,就直接去看了源码它会调用 cssdb,它是
CSS特性
的综合列表,可以到各个css特性 在成为标准过程中现阶段所处的位置,这个就使用stage
来标记,它也能告知我们该使用哪种postcss 插件
或者js包
来提前使用css 新特性。cssdb 包的内容的各个插件详细信息举例如下当我们设置了stage的时候,就会去判断
各个插件的stage
是否大于等于设置的stage,从而筛选出符合stage的插件集来处理css。最后我就从stage小于2的各个插件一个一个去试,终于在 postcss-custom-selectors 时候试成功了。然后就去看了该插件的功能,难道我字体图标的定义也是这样?果然如此:总结
上面介绍了四种换肤的方法,个人更加偏向于
antd
或者基于css 自定义变量
的写法,不过antd
基于less
在浏览器中的编译,less 官方文档中也说到了:所以编译速度是一个要考虑的问题。然后是
css 自定义变量
要考虑的可能就是浏览器中的兼容性问题了,不过感觉css 自定义变量
的支持度还是挺友好了的🤣🤣。ps:如果你还有其他换肤的方式,或者上面有说到不妥的地方,欢迎补充与交流🤝🤝
The text was updated successfully, but these errors were encountered: