Just Sword Wang's Blog

CSS in JS

CSS in JS这个命题,是在内部小组的一个简单分享,现在单独拿出来整理一下。

自React流行以来,混写HTML和JS乃至CSS的做法变成日常,虽然CSS在react里只有一个简单JS实现,但只用JS解决所有问题的思路也逐渐为人们所接受。在过往的数年中,各种CSS in JS的框架也层出不穷,这里简单梳理一下,毕竟自己也是个和CSS有着相当缘分的人:)

CSS & CSS in JS

CSS最初被设计为简单直观的描述性DSL,10年前甚至部分是有设计师直接使用的。不过web的持续发展不可避免的让前端细分到技术领域,我也算是一路看着CSS各种演变,从最开始的避免多类简单直接,到有多类,有原子化描述,有CSS-reset,Normalise,Minimum Page,到模块化的BEM管理,组件化的样式编写流程,语义化的组件范式,到bootstrap流行的时候达到了巅峰。

但CSS天生简单,毕竟是特型化的DSL,且设计之初就没打算搞复杂。这是的全局命名污染和冲突这一点成为无法略去之痛。现今的CSS in JS方案主要解决了这些问题:

  • 全局命名冲突
  • 直观的开发体验
  • 动态样式(样式根据数据变化)

特别是匹配上react这类all in js的解决路数,相当干脆的感觉。不过CSS in JS解决了某些问题,却也带来了另一些问题:

  • 性能损耗(运行时和SSR抽取)
  • SSR抽取样式会影响引用资源的上下文
  • 类名的语义化效果消失
  • 资源引用变为JS使得情况更为复杂

所以,基于上面这些问题,CSS in JS更像是CSS本身的补充。对于后台系统而言可能能达到替代的程度,因为后台并不需要SSR,并不关系语义,也往往不去不分资源的Host。

主流框架的做法

Ant Design (The world's second most popular React UI framework),号称是全球第二流行,颇有当年锤子自称全球第二好用的意味。它所使用样式系统是LESS,基本上作为一个团队的产品,在严格的管控下毫无问题。当然使用的人必须接受这种设定。加载antd会污染全局样式,特别是影响广泛的字体设定和box-sizing值。当然对大部分人来说也不是太大问题。

既然有世界第二,那么就有世界第一。

Material-UI (The world's most popular React UI framework),也是我打交道非常多的UI,我是一路看着它的样式系统不停修改过来的:

  • 起初使用的是LESS
  • 之后走了一条inline style覆盖计算的路子,但最近验证存在性能问题
  • 1.0的时候,开发团队评估了现存CSS in JS方案,最终从Jss, Aphrodite, CSS modules, styled-components, Fela一众后选中,选定JSS,看重的是其性能和各方面的能力
  • 如今已经已经基于JSS实现了styled-components API及Hook API,已经渐渐形成自己的一套CSS解决方案@mui/style,目前还是alpha状态

可见业界的各种探索也并未停歇。

CSS in JS 库

在库React: CSS in JS techniques comparison中,列举超过60种各类库,虽然这个库的作者有一段时间没有更新了,但至少记录这个曾经百花齐放的事态。

下面就列举一下比较常见的库

styled-components/styled-components
Visual primitives for the component age. Use the best bits of ES6 and CSS to style your apps without stress
emotion-js/emotion
CSS-in-JS library designed for high performance style composition
Khan/aphrodite
Framework-agnostic CSS-in-JS with support for server-side rendering, browser prefixing, and minimum CSS generation
css-modules/css-modules (react-css-modules)
Seamless mapping of class names to CSS modules inside of React components.
threepointone/glamor
inline css for react et al
paypal/glamorous (DEPRECATED)
Maintainable CSS with React
FormidableLabs/radium
A toolchain for React component styling.
rofrischmann/fela (react-fela)
State-Driven Styling in JavaScript
cssinjs/jss (react-jss)
JSS is an authoring tool for CSS which uses JavaScript as a host language.
styled-jsx
Full CSS support for JSX without compromises
styletron/styletron (styletron-react)
Toolkit for component-oriented styling

在这些命名里有很多glamor,glamorous,从中可以深切感受到到作者希望CSS in JS可以优雅美丽的存在的愿景。如今的CSS in JS领域其实基本已经稳定。styled-components以及后生emotion已经基本上牢牢占据前两的位置。

我特地拉一个流行库的github的star的历史记录,可以说是非常一目了然的形式:

有一个结论,就是无论styled-component还是emotion,都很好的利用了es6的Tagged Template Literals(标签模板),为CSS存在于JS中提供了优雅的展现形式。关于这部分具体内容,好像已经有点超过本篇篇幅,就放到下次继续了。


评论加载中...

Disqus提供评论支持,如果评论长时间未加载,请飞跃长城。