前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >7. 精读《请停止 css-in-js 的行为》

7. 精读《请停止 css-in-js 的行为》

作者头像
黄子毅
发布2022-03-14 15:44:10
1.9K0
发布2022-03-14 15:44:10
举报
文章被收录于专栏:前端精读评论

本周精读文章:请停止 css-in-js 的行为

1 引言

这篇文章表面是在讲 CSS in JS,实际上是 CSS Modules 支持者与 styled-components 拥趸之间的唇枪舌剑、你来我往。从 2014 年 Vjeux 的演讲开始,css-in-js 的轮子层出不穷。终于过了三年,鸡血时期已经慢慢过去,大家开始冷静思考了。

2 内容概要

styled-components

styled-components 利用 ES6 的 tagged template 语法创建 react 纯样式组件。消除了人肉在 dom 和 css 之间做映射和切换的痛苦,并且有大部分编辑器插件的大力支持(语法高亮等)。此外,styled-components 在 ReactNaive 中尤其适用。

styled-components 简单易学,引用官方源码:

代码语言:javascript
复制
import React from 'react';

import styled from 'styled-components';

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

<Title>
  Hello World, this is my first styled component!
</Title>

css-modules

顾名思义,css-modules 将 css 代码模块化,可以很方面的避免本模块样式被污染。并且可以很方便的复用 css 代码。

代码语言:javascript
复制
// 全局变量
:global(.className) {
  background-color: blue;
}

// 本地变量,其它模块无法污染
.className {
  background-color: blue;
}

.title {
  // 复用 className 类的样式
  composes: className;
  color: red;
}

react-css-modules

值得一提的是,文章的作者也是 react-css-modules 的作者。

react-css-modules 代码示例:

代码语言:javascript
复制
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './table.css';

class Table extends React.Component {
    render () {
        return <div styleName='table'>
            <div styleName='row'>
                <div styleName='cell'>A0</div>
                <div styleName='cell'>B0</div>
            </div>
        </div>;
    }
}

export default CSSModules(Table, styles);

react-css-modules 引入了 styleName,将本地变量和全局变量很清晰的分开。并且也避免了每次对 styles 对象的引用,本地 className 名也不用总是写成 camelCase。

另外,使用 react-css-modules,可以方便的覆盖本地变量的样式:

代码语言:javascript
复制
import customStyles from './table-custom-styles.css';

<Table styles={customStyles} />;

文章内容

3 精读

参与本次精读的同学有 黄子毅,杨森 和 camsong。该部分由他们的观点总结而出。

CSS 本身有不少缺陷,如书写繁琐(不支持嵌套)、样式易冲突(没有作用域概念)、缺少变量(不便于一键换主题)等不一而足。为了解决这些问题,社区里的解决方案也是出了一茬又一茬,从最早的 CSS prepocessor(SASS、LESS、Stylus)到后来的后起之秀 PostCSS,再到 CSS Modules、Styled-Components 等。更有甚者,有人维护了一份完整的 CSS in JS 技术方案的对比。截至目前,已有 49 种之多。

Styled-components 优缺点

优点

使用成本低

如果是要做一个组件库,让使用方拿着 npm 就能直接用,样式全部自己搞定,不需要依赖其它组件,如 react-dnd 这种,比较适合。

更适合跨平台

适用于 react-native 这类本身就没有 css 的运行环境。

缺陷

缺乏扩展性

样式就像小孩的脸,说变就变。比如是最简单的 button,可能在用的时候由于场景不同,就需要设置不同的 font-size,height,width,border 等等,如果全部使用 css-in-js 那将需要把每个样式都变成 props,如果这个组件的 dom 还有多层级呢?你是无法把所有样式都添加到 props 中。同时也不能全部设置成变量,那就丧失了单独定制某个组件的能力。css-in-js 生成的 className 通常是不稳定的随机串,这就给外部想灵活覆盖样式增加了困难。

css-modules 优缺点

优点

1、CSS Modules 可以有效避免全局污染和样式冲突,能最大化地结合现有 CSS 生态和 JS 模块化能力

2、与 SCSS 对比,可以避免 className 的层级嵌套,只使用一个 className 就能把所有样式定义好。

缺点:

1、与组件库难以配合

2、会带来一些使用成本,本地样式覆盖困难,写到最后可能一直在用 :global。

关于 scss/less

无论是 sass 还是 less 都有一套自己的语法,postcss 更支持了自定义语法,自创的语法最大特点就是雷同,格式又不一致,增加了无意义的学习成本。我们更希望去学习和使用万变不离其宗的东西,而不愿意使用各种定制的“语法糖”来“提高效率”。

就 css 变量与 js 通信而言,虽然草案已经考虑到了这一点,通过表达式与 attribute 通信,使用 js 与 attribute 同步。不难想象,这种情况维护的变量值最终是存储在 js 中更加妥当,然而 scss 给大家带来的 css first 思想根深蒂固,导致许多基础库的变量完全存储在 _variable.scss 文件中,现在无论是想适应 css 的新特性,还使用 css-in-js 都有巨大的成本,导致项目几乎无法迁移。反过来,如果变量存储在 js 中,就像草案中说的一样轻巧,你只要换一种方式实现 css 就行了。

总结

在众多解决方案中,没有绝对的优劣。还是要结合自己的场景来决定。

我们团队在使用过 scss 和 css modules 后,仍然又重新选择了使用 scss。css modules 虽然有效解决了样式冲突的问题,但是带来的使用成本也很大。尤其是在写动画(keyframe)的时候,语法尤其奇怪,总是出错,难以调试。并且我们团队在开发时,因为大家书写规范,也从来没有碰到过样式冲突的问题。

Styled-components 笔者未曾使用过,但它消除人肉在 dom 和 css 之间做映射的优点,非常吸引我。而对于样式扩展的问题,其实也有比较优雅的方式。

代码语言:javascript
复制
const CustomedButton = styled(Button)`
  color: customedColor;
`;
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端精读评论 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 引言
  • 2 内容概要
    • styled-components
      • css-modules
        • react-css-modules
          • 文章内容
          • 3 精读
            • Styled-components 优缺点
              • 优点
              • 缺陷
            • css-modules 优缺点
              • 优点
              • 缺点:
            • 关于 scss/less
            • 总结
            相关产品与服务
            对象存储
            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档