大家对CSS in JS怎么看?

#1

最近在学习React,找到一个UI组件库 material-ui,发现它的css是写在JS里面的,然后找到这个slide,是Facebook 前端基础设施团队的人写的,感觉说的很有道理。

我现在的看法是,将来如果出现很多组件库的话,将CSS写在JS里面的确是避免冲突的好办法,不知道大家怎么看?

#2

如果是项目超级大超级复杂,确实能解决css冲突问题,并且能解决css的工程问题。缺点就是css和js紧耦合了,如果需要调整样式可能不太方便了。

1 Like
#3

同一控件的CSS和JS本来就是在描述同一个东西
所以说不上是耦合

2 Likes
#4

我觉得是一个不错的方案,但是方案都是有利弊的,在我看来好处就是css不会冲突了,问题是这个方案应该怎么实现?

#5

实现应该不困难,JSX里本来就是可以写样式的,最后输出的就是内联的样式。然后组件不应该再修改,如果要覆盖样式,可以从外部覆盖。

#6

组件里面内联的样式,从外面怎么覆盖?

通过 props 传递进去合并上去吗?

#7

实现的方式很简单,但是css不能分派给UI进行编写了。 样式复用部分也可以通过js依赖实现。

#8

我好像理解错了,在material-ui里是要修改组件的style prop的: http://material-ui.com/#/customization/inline-styles

#9

实现用webpack直接require css 文件就行了,并且可以在打包的时候指定包在js文件里,包括小图片,一样可以转成base64打包,好处还是很多的,比如引入某个控件的时候,只要引入js文件就行了

1 Like
#10

scoped 的 CSS 实现就 Web Components 和 inline CSS 两种, 只能等实现.
inline CSS 目前最可行, 但是也挺难的… 看别人用的效果再开始.

#11

在这里的评论中有我的一些观点,不知道 题叶 更倾向于哪一种方案?

#12

两周都不错, 观望, 看哪个成熟就跟进.

#13

观望ing

#14
script type="template" id="register_form">
    <style>.dui-dialog .dui-dialog-shd{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;opacity:1;filter:alpha(opacity=100);background:0}.dui-dialog .hd{padding:0}.dui-dialog .bd{padding:0!important;margin:0!important}.dui-dialog .dui-dialog-content{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border:0;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.2);-moz-box-shadow:0 0 10px rgba(0,0,0,0.2);box-shadow:0 0 10px rgba(0,0,0,0.2)}.dui-dialog .dui-dialog-close,.dui-dialog .dui-dialog-close:link,.dui-dialog .dui-dialog-close:visited,.dui-dialog .dui-dialog-close:hover,.dui-dialog .dui-dialog-close:active{color:#fff;font-size:9px}#register_block{letter-spacing:-4px;height:400px}#legend{font-size:18px;color:#333;padding:0}form.register{width:285px;padding:40px 35px 0 37px;letter-spacing:0;float:left}form .spec{background-color:#eef1f0;margin-top:12px;padding:8px 10px;position:relative}form .spec label{margin-right:25px}#user_name{ime-mode:disabled}form .item{color:#666}form .item .text{border:0 none;color:#333;background-color:#eef1f0;width:170px;position:absolute;left:63px;top:10px}form .item .tip{color:#888}form .item .text:focus{border:0 none;outline:0}form .item label{float:none}form .item input{margin:0}form .recsubmit{clear:both;padding-top:30px;position:relative}form .recsubmit #btn-submit{display:block;background-color:#9dd6c5;width:110px;height:35px;line-height:35px;text-align:center;border:0 none;color:#fff;font-size:14px;float:right;cursor:pointer;outline:0}form .recsubmit #btn-submit:hover{background-color:#bae2d6;color:#5a5a5a}form .recsubmit .loading{background:url(http://img3.douban.com/f/fm/c82b5ca7f9deb9e7a04f23c5a9314d2c346196e5/pics/ajax-loader.gif) no-repeat 0 0;width:16px;height:16px;position:absolute;top:40px;right:120px;display:none}.alternative{width:190px;height:400px;vertical-align:top;background-color:#5a5a5a;letter-spacing:0;float:right;color:#aaa;position:relative}.third-party-mod{position:absolute;left:25px;top:35px;width:160px}.third-party-mod ul{color:#c8f4e7;letter-spacing:-4px;margin-top:5px;height:19px;line-height:19px}.third-party-mod li{display:inline-block;vertical-align:top;*display:inline;zoom:1;*vertical-align:baseline;margin-right:5px;letter-spacing:0;*margin-right:3px;*font-size:8px}.third-party-mod a{color:#c8f4e7;margin-right:5px;font-size:12px;*margin-right:3px}.third-party-mod a:link{color:#c8f4e7}.third-party-mod a:visited{color:#c8f4e7}.third-party-mod a:hover{text-decoration:underline;background:0}.third-party-mod a:active{text-decoration:underline}div.captcha{width:130px;float:left;margin-right:5px;*margin-right:0}#register_block div.captcha label{margin-right:12px}#register_block div.captcha input.text{width:72px}img.captcha{margin-top:15px;cursor:pointer}.agreement{margin-top:9px;width:170px;float:left;*width:160px}.agreement a,.agreement a:link,.agreement a:hover{color:#5b9}.ending{background:url(http://img3.douban.com/f/fm/a2c70cc12980bb9063a6beb9606e20360b2299d0/pics/fm/home/finish_signup.png) no-repeat center center}.login-mod{position:absolute;left:25px;width:160px}.login-mod{bottom:25px}.login-mod p{line-height:8px;color:#aaa}.login-mod a{border:1px solid #666;display:block;width:130px;height:30px;padding-left:10px;line-height:30px;font-size:14px;margin-top:10px;color:#fff;cursor:pointer}.login-mod a:link{color:#fff}.login-mod a:visited{color:#fff}.login-mod a:hover{background-color:#666}.login-mod a:active{color:#fff}</style>
    <div id="register_block">

douban就是在模板里面加载局部Css,这样模板可以以到处复用, 模板换到另一个地方,就不用复制整个css,或者分柴出模板用到的css

#15

我想组件化的目标是,让开发人员能方便的组合组件进行开发,将css和html都包含在一起,让component变成一个黑盒,是一种非常有效的方式。
而css in js是实现这中目标的手段之一,做到css with component才是最终目标。

目前我觉得组件和css揉合在一起最大的问题是对原始css的样式的重新定制问题,component是一个黑盒,不能像以前那样直接替换css文件就可以了。这里有两个问题,
第一是原始css被嵌入了组件中,如果要重新定制css的话,那么就等于无用的css也包含在内
第二是如何更好的支持的css重新定制,而不失可读性、可维护性

目前我还没有看到现有的方法可以解决我的问题。这应该需要对webpack打包工具动手脚来,或许还需要一套对组件规范才行。

inline style的方式,很可惜,写animation比较麻烦,react style这个package不错。

另外,我觉得scoped不是大问题,可以人为规避,也可以通过编译器解决。
最后,我还是觉得import "xxx.less"是最好的选择,

2 Likes
#16

对于css in js,发现了这个 https://github.com/cssobj/cssobj 可以封装CSS样式,以及动态更新样式

可以看下demo: https://cssobj.github.io/cssobj-demo/

@jiyinyiyong 能否指点一二?

#17

对这个不了解, 我是用不可变数据直接 merge 的

#18

有没有人用过 Khan Academy 的 aphrodite

看着不错的样子,支持 pseudo-selectors

#19

目前项目中也用到的css-in-js的解决方案,大致实现是:

  1. 使用csjs库加上一些简单的封装
  2. 在定义组件时,通过封装的方法,把组件的css转成string合并到css池子中
  3. 在app.js加载后,把池子中的css样式inject到页面中的style标签里

因为最终生成的是style标签,所以相比其他css-in-js方案,最大的优势是能原生支持:
CSS media queries, pseudo-classes, keyframe animations 等,同时依赖较少。

缺点是需要用ES6 template strings的方式来写css,缺少编辑器支持: