如果你用组件化的前端方案,比如React这种,那么毫无疑问,css in js方案要比传统的css方案要好。

css in js 有两点不可撼动的优越性。

1. 你不需要再为命名的css的 class name而思考了。传统的css方案,因为class name是全局的,你就要保证它的唯一性,你要把你的组件名等各种namespace作为class name的前缀,以保证唯一性。css in js主要是解决了这一点。

2. css直接使用js的变量。css是不能定义变量的,如果你使用less或者sass,确实可以定义变量,但那主要是为了共享,是没有办法使用js的变量的。这一点问题不大,不用js变量也能写的好好的,只是稍微麻烦一点。

从第一点出发,看看我所希望css in js是什么样的。然后再去看styled-component, emotion和jss是怎么做的,最后再去评价。

// button.css
.my-button {
  background-color: withe;
}
import './button.css'
const App = props => {
  return <div css="my-button"></div>
}

首先是一个css样式,和正常的css一样。然后用的时候把css的class name放到css(或者其他一个property)里面。渲染的结果里面并不包含my-button,而是一个生成的唯一的class name。

这种写法用法上和传统的css写法基本一样。

当然这只是我期待的css in js,应该是不存在这种开源代码的。理论上能不能实现我也不清楚,能想到的是写个babel loader去搞,但是对babel loader具体的职责我并不懂。

前面说了,这只是基于第一点而期待的,如果再加上第二点,那么简单这么做是不行的,因为上面本质上还是用的css样式,没办法吧把js变量放进去。

styled-component的做法:

const Button = styled.div`
  background-color: white;
`
const App = props => {
  return <Button />
}

应该说这个脑洞非常大,直接把css作为了一个组件,而不是一个属性(className,style,css等等)。

emotion的做法:

const App = props => {
  return <div className={css`
    background-color: white;
    `}></div>
}

这其实就是在代替内联样式。

或者这样:

const App = props => {
  return <div css={{backgroundColor: 'white'}}></div>
}

而如果你用react自带的话,只是把上面的css换成style

const App = props => {
  return <div style={{backgroundColor: 'white'}}></div>
}

当然渲染结果是有区别的,react自带的是内联样式,emotion渲染的是class 样式。

可以猜出来,emotion的初衷就是为了消灭内联样式。

jss的做法

const useStyles = createUseStyles({
  backgroundColor: 'white',
})
const App = props => {
  const { backgroundColor } = useStyles();
  return <div className={backgroundColor}></div>
}

和emotion的css方案差不多,具体样式都是用的js语法(backgroundColor: ‘white’,),而不是css语法(background-color: white;)。

区别是官方样例的倾向问题。jss更倾向于把一个组件内的所有css作为一个整体(当然你也可以分成多个useStyles)。

事实上jss和emotion用法基本是一样的,你用emotion同样可以把组件的css作为一个整体去定义。

我自己的倾向

styled-component是反人类的设计。原因是它会造成Component的混乱不堪,代码难以阅读,至少在react中用是这样。你没有办法非常容易的区分一个styled component和正常的Component,这样在读代码的时候就要思考它到底是什么。

emotion和jss上面分析了,区别不大。jss好像不支持css的语法方案?(事实上比较流行的几个css in js方案基本都是互通的。象jss和emotion都可以象styled-component那样去写)。

只是jss的文档更好一点。emotion的文档是匪夷所思的,把代码象内联样式一样去写???WTF!