(向大家介绍一个我写的另类 css-in-js 库,顺便求一些建议、星星或者 PR )
css-rendergithub.com在创建一个 UI 组库的时候,我遇到了几个问题:
- 某个特定组件,需要内置的不同颜色过多,同样的逻辑重复很多遍,打包出来的样式即使 gzip 之后体积依然在
10KB
左右,不压缩体积完全不能看。如果能在浏览器动态生成,能节省很多打包体积(用 CPU 时间换带宽,在值得的时候)。 - 重复的逻辑是用 Sass 实现的,没有办法做到在浏览器端接受某个用户输入的颜色,即使这段逻辑已经用 Sass 实现了,除非我在浏览器解析 Sass,但是那样体积又太大了。
于是我开始着手解决这个问题,核心有几个需求:
- 需要能在浏览器端(动态,可接受用户输入)生成 CSS 并挂载。
- 自身需要够小,不能节省的体积比引入的体积还要大。
- 对
@keyframes
,::before
,:hover
等选择器友好,光靠inline
不够用,因为动画可能也是元素样式的一部分。 - 尽量拥有较高的表达能力,能让一部分 Sass 代码以比较低的成本迁入。
- 能在 Node.js 端渲染就更好了。
所以有了开头那个库:它不是为了取代其他的样式方案,而是试图和它们共存,弥补其中的一些不足。
下面放几个例子:
- 基本例子
// 最简单的例子
import CSSRender from 'css-render'
const {
c
} = CSSRender()
const style = c('body', {
margin: 0,
backgroundColor: 'white'
}, [
c('&.dark', {
backgroundColor: 'black'
}),
c('.container', {
width: '100%'
})
])
/** 作为字符串使用 */
console.log(style.render())
/**
* 或者挂载于 document.head,
* 下面两行只在浏览器工作,不要在 node.js 中调用
*/
style.mount()
// ...
style.unmount()
输出
body {
margin: 0;
background-color: white;
}
body.dark {
background-color: black;
}
body .container {
width: 100%;
}
2. 一定程度的动态能力
const style = c('.button', ({
props
}) => ({
color: props.color
}))
console.log(style.render({ color: 'red' }))
console.log()
console.log(style.render({ color: 'blue' }))
输出
.button {
color: red;
}
.button {
color: blue;
}
3. 对于不能内联的样式友好
console.log(c('@keyframes my-animation', {
from: {
color: 'white'
},
to: {
color: 'black'
}
}).render())
输出
@keyframes my-animation {
from {
color: white;
}
to {
color: black;
}
}
4. 一定程度上能模仿 mixin 的效果(比如常见的 BEM 写法)
import CSSRender from 'css-render'
import CSSRenderBEMPlugin from '@css-render/plugin-bem'
/**
* common js:
* const { CSSRender } = require('css-render')
* const { plugin: CSSRenderBEMPlugin } = require('@css-render/plugin-bem')
*/
const cssr = CSSRender()
const plugin = CSSRenderBEMPlugin({
blockPrefix: '.c-'
})
cssr.use(plugin)
const {
cB, cE, cM
} = plugin
const style = cB(
'container',
[
cE(
'left, right',
{
width: '50%'
}
),
cM(
'dark',
[
cE(
'left, right',
{
backgroundColor: 'black'
}
)
]
)
]
)
/** use it as string */
console.log(style.render())
输出
.c-container .c-container__left, .c-container .c-container__right {
width: 50%;
}
.c-container.c-container--dark .c-container__left, .c-container.c-container--dark .c-container__right {
background-color: black;
}
感谢大家的阅读,鞠躬。